Lenses http://hackage.haskell.org/package/lenses与标准 Haskell 相比,它似乎没有任何缺点,同时具有显着的优点:有什么理由我不应该尽可能使用镜头吗?有性能方面的考虑吗?此外,模板 Haskell 是否有任何显着的开销?
镜头形成了在数据构造函数上使用直接闭包的替代方案。因此,镜头与直接使用函数和数据构造函数具有大致相同的注意事项。
因此产生一些缺点:
-
每次修改镜头时,都可能会导致(重新)创建许多对象。例如,如果您有以下数据结构:
A { B { C { bla = "foo" } } }
...以及镜头类型Lens A String
,您将创建一个新的A
, B
and C
每次你“修改”那个镜头时。这在 Haskell 中并不罕见(创建大量对象),但对象创建隐藏在镜头后面,因此很难发现它是潜在的性能下降。
- A lens could also create inefficiencies due to the "mapping function" being used. For example, if you make a lens that modifies the 26th element in a list, it might cause a lot of slowdowns due to the lookup time.
和优点:
- 透镜与普通记录相结合,可以与状态单子完美地结合使用(参见data-lens-fd http://hackage.haskell.org/package/data-lens-fd例如),这使得有可能avoid由于广泛的数据共享,大多数时候都会重新创建大量对象。例如,参见focus http://hackage.haskell.org/packages/archive/data-lens-fd/2.0.2/doc/html/Data-Lens.html#v%3afocus函数,以及类似的使用模式
withSomething
Snap Web 框架中的功能。
- 显然,镜头实际上不会就地修改任何内存,因此当您需要在并发上下文中推理状态时,它们非常有用。因此,在处理各种图表时,透镜将非常有用。
然而,镜头并不总是与数据构造函数上的闭包同构。以下是一些差异(取data-lens http://hackage.haskell.org/package/data-lens作为此处的实现):
- 大多数镜头实现使用某种形式的数据类型来将“访问器”和“修改器”存储为一对。为了
data-lens
,这是Store comonad http://hackage.haskell.org/packages/archive/comonad-transformers/latest/doc/html/Control-Comonad-Trans-Store.html#t%3aStore。这意味着每次创建镜头时,由于创建的数据结构都会产生非常小的额外开销。
- 由于镜头依赖于某些未知映射的值,因此推理垃圾收集可能会变得更加困难,并且您可能会遇到(逻辑)内存泄漏,因为您忘记了您正在使用依赖于某些大内存块的非常通用的镜头。举个例子,一个镜头访问某个大向量中的一个元素,它与另一个镜头组合而成,从而隐藏了第一个镜头,使得很难看出组合的镜头仍然依赖于大量的内存。
模板 Haskell 代码在编译时运行,并且不会影响镜头的运行时性能。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)