rampion
rampion

Reputation: 89043

Workaround to return a lens from a monadic action

Ran into this issue when playing with today's advent of code problem.

Say I have:

data Cache = Cache { _a :: Int, _b :: Int }
makeLenses ''Cache

type Register = Lens' Cache Int

Using Parsec, I can parse the character 'a' as a :: Register and the character 'b' as b :: Register.

register = a <$ char 'a' <|> b <$ char 'b'

which, alone, compiles just fine.

The trouble is when I give register the explicit type Stream s m Char => ParsecT s u m Register, ghc complains that it wants to give it the type (Functor f, Stream s m Char) => ParsecT s u m ((Int -> f Int) -> Cache -> f Cache).

I think I understand its reasoning - it wants to float the typeclass constraints out as a far as possible; this is just slightly inconvenient to me for purposes of documenting register.

Is there a standard workaround for situations like this?

Upvotes: 1

Views: 75

Answers (1)

rampion
rampion

Reputation: 89043

The solution that worked for me was to use ALens rather than Lens, as

This type can also be used when you need to store a Lens in a container, since it is rank-1.

Then I just replaced my Lens operators ^. and %~ with their ALens equivalents, ^# and #%~.

Upvotes: 1

Related Questions