haskell - 使用镜片有什么好处和坏处?

标签 haskell lenses

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

最佳答案

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

由于这个原因的一些缺点:

  • 每次修改镜头时,都可能会导致(重新)创建大量对象。例如,如果你有这个数据结构:
    A { B { C { bla = "foo" } } }
    

    ...以及 Lens A String 类型的镜头,您将创建一个新的 A , BC每次你“修改”那个镜头。这在 Haskell 中并不少见(创建大量对象),但对象创建隐藏在镜头后面,因此很难将其视为潜在的性能接收器。
  • 由于使用了“映射功能”,镜头还可能导致效率低下。例如,如果你制作一个修改列表中第 26 个元素的镜头,它可能会由于查找时间而导致很多减速。

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

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

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

    关于haskell - 使用镜片有什么好处和坏处?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10774614/

    相关文章:

    haskell - 如何从 UTCTime 中提取特定的时间分量?

    haskell - 获取循环列表的第一个重复元素

    haskell - Numeric.AD 和打字问题

    Haskell Control.镜头移动棱镜

    haskell - 使用 Maybe 遍历嵌套记录的更短方法

    java - 哪些语言支持 Lenses 或类似的方式来更新不可变的嵌套结构?

    haskell - yesod 中带有自定义验证的文件上传字段

    haskell - 什么是非线性模式

    haskell - 为给定的数据类型编写一个在镜头上具有多态性的函数?

    javascript - 使用透镜将柯里化(Currying)函数映射到数组上