Control.Lens是否有性能开销?

8

我很欣赏Control.Lens包。它真的有助于稍微弱一些的Haskell记录语法。 我正在处理一些库的部分,其中性能是一个问题。 有人知道使用以下方式通过类型类公开的简单镜头与在函数中使用基本模式匹配相比,性能惩罚会是什么吗?像这样使用Lenses有潜力成为解决记录命名空间冲突问题的好方法。 我可以自己设置一些基准测试,但很好奇是否有人能帮我省点麻烦。谢谢。

镜头类

class LensX v where
  _x :: Functor f => (Double -> f Double) -> v -> f v

class LensY v where
  _y :: Functor f => (Double -> f Double) -> v -> f v

class LensZ v where
  _z :: Functor f => (Double -> f Double) -> v -> f v 

镜头实例

instance LensX Vec3 where
  _x f (Vec3 x y z) = fmap (\x' -> Vec3 x' y z) (f x)

instance LensY Vec3 where
  _y f (Vec3 x y z) = fmap (\y' -> Vec3 x y' z) (f y)

instance LensZ Vec3 where
  _z f (Vec3 x y z) = fmap (\z' -> Vec3 x y z') (f z)

提供Lenses的模块不需要导入Control.Lens包,这很棒。该库的使用方法在此页面https://github.com/ekmett/lens/中有描述。


5
你应该对其进行基准测试。 - augustss
1个回答

8
您在使用这种类型的镜头时会付出一定的性能代价。这是由于所有具有约束条件的高级类型都会导致字典传递发生。

这是少数情况之一,您需要返回到 data-lens,它没有这个问题,甚至可以使您的代码运行更快。如果您解码了 Store comonad 的间接引用,data-lens 使用的是最简单的镜头表示方法之一:

newtype Lens s a = Lens (s -> (a, a -> s))

虽然该库本身不支持多态透镜,但您可以构建自己的透镜类型,以实现高性能:

newtype Lens s t a b = Lens (s -> (a, b -> t))

针对您的特定需求,您可能也会对linear包感兴趣。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接