Haskell, Lenses, Getters, and Setters

Viewed 1996

I'm having trouble understanding all the nuances of the lens library in Haskell.

Suppose I have the following lens

activePlayer :: Lens' Game Player
activePlayer = lens get set
    where
        get (Game {_players = (index, seq) }) = S.index seq index
        set g@(Game {_players = (index, seq) }) player =
            g { _players = (index, S.update index player seq) }

Performing the following at the ghci prompt works with no problems:

> :t do{use (activePlayer); activePlayer.= undefined}
     :: Control.Monad.State.Class.MonadState Game m => m ()

However when I try and parameterize it into a function I get the following error.

> :t \p -> do{use p; p.=undefined}
<interactive>:1:17:
    Couldn't match type `Accessor a0 a0' with `Mutator b0'
    Expected type: ASetter s0 s0 a0 b0
      Actual type: Getting a0 s0 a0
    In the first argument of `(.=)', namely `p'
    In a stmt of a 'do' block: p .= undefined
    In the expression:
      do { use p;
           p .= undefined }

It looks like p is getting inferred as an Accessor, when I want it to be inferred as a full Lens. I tried forcing p to be a Lens with the following, but ghci complained about RankNTypes in Lens' a b.

:t \p -> do{use p; p.=undefined} :: Lens' a b -> m c

I would greatly appreciate it if anyone could help me figure out why p is being inferred the way it is, and how I can make it behave as a full Lens.

1 Answers
Related