Search code examples
haskelllenses

How to use the "Of" lenses? (Haskell)


I want to write:

minimum $ map _x elems

using lenses. I want to use the minimumOf lens, but I can't figure out how to use it from its type.

I'm looking for something like

elems ^.. minimumOf x

but it does not type check:

Prelude Control.Lens Data.Map> let elems = [(1,2),(3,4)] :: [(Double, Double)]
Prelude Control.Lens Data.Map> elems ^.. minimumOf _1

<interactive>:62:11:
    Couldn't match type ‘Maybe a0’
                  with ‘[(Double, Double)]
                        -> Const (Data.Monoid.Endo [a]) [(Double, Double)]’
    Expected type: Getting (Data.Monoid.Endo [a]) [(Double, Double)] a
      Actual type: (a -> Const (Data.Monoid.Endo [a]) a) -> Maybe a0
    Relevant bindings include it :: [a] (bound at <interactive>:62:1)
    Possible cause: ‘minimumOf’ is applied to too many arguments
    In the second argument of ‘(^..)’, namely ‘minimumOf _1’
    In the expression: elems ^.. minimumOf _1

Solution

  • The documentation seems reasonably clear on the usage -- how would you improve it?

    minimumOf isn't a lens (or traversal or anything) -- it takes a fold (or traversal or lens or something -- but it's not useful to use it with a lens, because you're taking the minimum of exactly one thing) and looks for the minimum value that it focuses on in a structure. E.g.

    λ> minimumOf (traverse . _1) [(1,'a'),(2,'b')]
    Just 1
    

    It generalizes the Prelude function minimum -- which always takes a list -- to a function which takes any sort of value, along with instructions for getting a bunch of things out of that value, and computes the minimum of those things.