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.
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)
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/.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With