Search code examples
haskellhaskell-lens

With the Haskell lens library, how do I treat getters as `first class'?


I've noticed I'm commonly building functions that get values using lenses, apply some function to the values and return the result. For example, to sum the elements of a pair \pair -> (pair ^. _1) + (pair ^. _2)

I feel like there should be some combinator to combine getters first class and return another getter (maybe of type (b -> c -> d) -> Getter a b -> Getter a c -> Getter a d). Any help?


Solution

  • As is explained on the top of Control.Lens.Getter, a Getter a b is isomorphic to (a -> b). This means that they contains the same information and can be changed into each other at will. We can turn them into each other by using functions that the lens library provide:

    fromGetter :: Getter a b -> (a -> b)
    fromGetter g = view g
    
    toGetter :: (a -> b) -> Getter a b
    toGetter = to
    

    With this knowledge you can use the Applicative instance for (->), as J. Abrahamson has shown, to create the function you want:

    myCombinator :: (b -> c -> d) -> Getter a b -> Getter a c -> Getter a d
    myCombinator fn g1 g2 = toGetter (fn <$> fromGetter g1 <*> fromGetter g2)