【问题标题】:What are the advantages and disadvantages of using lenses?使用镜片有什么好处和坏处?
【发布时间】:2012-06-02 05:28:59
【问题描述】:

Lenses 似乎没有任何缺点,但比标准 Haskell 具有显着优势:我有什么理由不应该尽可能使用镜头吗? 是否有性能方面的考虑?此外,模板 Haskell 是否有任何重大开销?

【问题讨论】:

  • 真的吗,马辛?中级 Haskell 用户应该了解镜头;我在几个流行的 Haskell 项目中见过它们。这是stackoverflow link that somewhat explains them
  • 我添加了一个链接。没有理由投反对票。
  • @reltone Stackoverflow 不是面向中级 Haskell 用户的站点。它适用于所有想学习编程的人(在常见问题解答的参数范围内,更可惜)。
  • 就我的口味而言,当前的 Lens 包没有添加任何足够引人注目的东西,值得添加额外的库依赖项和 Template Haskell - 相反,我使用 Control.Applicative haskell.org/pipermail/haskell-cafe/2010-September/083543.html。注意 - 我现在使用简单的辅助函数来解决嵌套记录更新问题。
  • @Marcin 如果你读到这篇文章并想知道的话,用谷歌搜索并不难,任何回答的人都应该对这个主题有相当多的了解。我同意 Cat Plus Plus:投反对票是不合理的。另外,现在一个链接,所以如果它是你的反对意见,请删除它。

标签: haskell lenses


【解决方案1】:

镜头形成了在数据构造函数上使用直接闭包的替代方案。因此,镜头与直接使用函数和数据构造函数大致相同。

因此的一些缺点:

  • 每次修改镜头时,都可能会导致(重新)创建大量对象。例如,如果你有这样的数据结构:

    A { B { C { bla = "foo" } } }
    

    ...和Lens A String 类型的镜头,您将在每次“修改”该镜头时创建一个新的ABC。这在 Haskell 中并不少见(创建大量对象),但对象创建隐藏在镜头后面,因此很难将其作为潜在的性能接收器。

  • 由于使用了“映射功能”,镜头也可能导致效率低下。例如,如果您制作一个修改列表中第 26th 元素的镜头,它可能会由于查找时间而导致很多减速。

还有优点:

  • 镜头与普通记录相结合,可以很好地与状态单子一起使用(参见data-lens-fd 示例),这可以避免在大多数情况下重新创建大量对象时间,由于广泛的数据共享。例如,请参阅 focus 函数,以及在 Snap Web 框架中使用 withSomething 函数的类似模式。
  • 显然,镜头实际上并没有就地修改任何内存,因此当您需要在并发上下文中推理状态时,它们非常有用。因此,镜头在处理各种图形时非常有用。

然而,镜头并不总是与数据构造函数上的闭包同构。以下是一些不同之处(这里以data-lens 作为实现):

  • 大多数镜头实现使用某种形式的数据类型将“访问器”和“修改器”存储为一对。对于data-lens,它是Store comonad。这意味着每次创建镜头时,都会因为创建数据结构而产生非常小的额外开销。
  • 由于镜头通过一些未知映射依赖于值,因此垃圾收集的推理可能会变得更加困难,并且您可能会遇到(逻辑)内存泄漏,因为您忘记了您使用的是一个非常通用的镜头,该镜头依赖于一些大块记忆。例如,一个镜头访问某个大向量中的元素,该镜头与另一个镜头组合,因此隐藏了第一个镜头,因此很难看出组合镜头仍然依赖于大量内存。

模板 Haskell 代码在编译时运行,不会影响镜头的运行时性能。

【讨论】:

    【解决方案2】:

    我假设 data-lens 包。 Lenses 在数据类事物(记录、元组、地图等)方面对我来说表现得非常好。事实上,它们有时甚至比正常方法表现得更好,可能是因为更好的共享。就性能而言,它产生的性能与您手动编写的代码大致相同。

    但是,有些类似功能的东西,镜头可能会受到惩罚。例如,我记得至少有一次使用过这样的镜头:

    result :: (Eq a) => a -> Lens (a -> b) b
    

    虽然查询非常快,但我偶尔会覆盖函数的某些结果值以将其调整到特定场景,这相当于将函数的主体包含在一个大的 if 中。当然,性能影响与镜头本身无关,但值得注意。

    【讨论】:

      猜你喜欢
      • 2011-05-14
      • 1970-01-01
      • 2011-08-14
      • 1970-01-01
      • 1970-01-01
      • 2011-01-14
      • 1970-01-01
      • 1970-01-01
      • 2021-02-01
      相关资源
      最近更新 更多