镜头似乎并不具备,同时具有比标准哈斯克尔显著优势任何缺点: 是否有任何理由我不应该尽可能使用镜头? 是否有性能方面的考虑? 此外,没有模板哈斯克尔有任何显著的开销?
Answer 1:
透镜形成以使用直接封闭件上的数据构造的替代方案。 因此透镜具有近似相同的警告直接使用功能和数据构造。
有些是因为这个缺点的:
每次修改一个镜头的时候,你可能导致一些潜在大量的对象是(重新)创建的。 举例来说,如果你有这样的数据结构:
A { B { C { bla = "foo" } } }
...和类型的镜头
Lens A String
,您将创建一个新的A
,B
和C
每次“修改”那个镜头。 这是没有什么不寻常在Haskell(创建大量的对象),但对象创建隐藏背后的镜头,使得它很难被发现为潜在的性能水槽。- 透镜还可以创建由于所使用的“映射函数”低效率。 例如,如果你作出这样的修改26 个元素列表中的一个镜头,则可能会导致大量的怠工的,由于查找时间。
和优点:
- 透镜,在与正常记录组合,可以精美的状态单子(参见
data-lens-fd
的例子),并且这使得能够避免重新创建大量对象的大部分时间中,由于大量的数据共享。 参见例如focus
功能,并使用类似的模式withSomething
在管理单元网络框架的功能。 - 镜头显然不实际修改就地任何记忆,所以他们是非常有用的,当你需要推理状态并发的情况下。 因此镜头会用各种图形处理时是非常有用的。
镜头并不总是同构于对数据构造倒闭,但是。 这里有一些差异(以data-lens
作为实现这里):
- 大多数透镜实现使用某种形式的数据类型来存储“存取器”和“增变”为一对。 对于
data-lens
,它的Store
comonad 。 这意味着每次创建一个镜头的时候,就会有一个非常小的额外的开销,由于正在创建的数据结构。 - 由于镜头通过一些不知名的映射取决于值,它可能会变得难以推理垃圾收集,因为你忘了,你使用的是依赖于一些大的内存块一个非常通用的镜头,你可能会得到(逻辑)内存泄漏。 举个例子来说,访问的元素在一些大的矢量,它是由与另一透镜从而隐藏了第一透镜,使得难以看到由透镜仍取决于大量的存储器的透镜。
模板Haskell代码运行在编译的时候,并不会影响任何镜头的运行时性能。
Answer 2:
我假设该数据包镜头 。 镜头的表现非常出色,我对数据状的东西(的记录,元组,地图等)。 事实上,他们有时甚至可能是因为更好地分享执行比正常的做法更好。 在性能方面,它生产大约为代码,你的手都写相同的性能。
不过,也有功能类似的事情,为此,镜头可以有一个点球。 例如,我记得使用透镜这样一个至少一次:
result :: (Eq a) => a -> Lens (a -> b) b
虽然查询速度非常快,我偶尔会推翻功能的某些结果值将其调整到特定的情况下,这相当于在一个大的封闭功能的身体if
。 对性能的影响是不相关的透镜本身,当然,但它是值得注意的。
文章来源: What are the advantages and disadvantages of using lenses?