8
votes

I am appreciating the Control.Lens package. It really helps with the slightly weak Haskell record syntax. I'm working on some parts of a library where performance is a concern. Does anyone know what the performance penalties would be, if any, of using a simple lens exposed through a type class as shown below as compared to basic pattern matching in a function? Using Lenses like this has the potential to be a great work around for the record namespace conflict problem. I could setup some benchmarks my self but am curious if anyone can save me the trouble. Thanks.

The Lens classes

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 

The Lens instances

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)

The module providing the Lenses does not have to import the Control.Lens package, which is awesome. The use of the library is described on this page https://github.com/ekmett/lens/.

1
You should benchmark it.augustss

1 Answers

8
votes

You pay a small performance penalty for this type of lenses. It comes from all the higher rank types with constraints that cause dictionary passing to happen.

This is one of the rare cases when you want to go back to data-lens, which doesn't have that problem and can even make your code faster. Data-lens, if you decode the Store comonad indirection, uses about the most straightforward representation you can have for a lens:

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

While the library doesn't support polymorphic lenses by itself you can build your own lens type that does and still gives you the high performance:

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

For your particular purpose you may also be interested in the linear package.