5

I am changing some code that used to run inside a StateT monad to run inside of StateP from Control.Proxy. However, some of my code (e.g. the %= operator from Control.Lens) requires a MonadState instance. Is it safe/correct for me to just add such an instance? This seems like something that is most correctly handled by a library (in this case, Control.Proxy).

ajp
  • 1,723
  • 14
  • 22

1 Answers1

4

Yes, this is safe. The instance you want is:

instance (Monad m, Proxy p) => MonadState s (PS.StateP s p a' a b' b m) where
    get = PS.get
    put = PS.put

I just want to briefly note that in pipes-4.0.0 (which is on Github) the proxy transformers are no longer necessary and the same extensions are outsourced to monad transformers in the base monad. This means that instead of:

Consumer (StateP s p) a m r

... you would use:

Consumer a (StateT s m) r

This means that you would then just be able to write:

lift $ myLens %= f

However, I still plan on adding MonadState instances for Proxy anyway, although perhaps in a separate package (I still haven't decided whether to include them in the main library yet). They would look like this:

instance (MonadState s m) => MonadState s (Proxy a' a b' b m r) where
    put s = lift (put s)
    get   = lift get
Gabriella Gonzalez
  • 34,863
  • 3
  • 77
  • 135
  • many thanks! however, this seems to be not quite correct - I get the following error: – ajp Jun 26 '13 at 08:09
  • `Kind mis-match The second argument of 'MonadState' should have kind '* -> *', but 'Proxy a' a b' b m r' has kind '*' In the instance declaration for 'MonadState s (Proxy a' a b' b m r)'` – ajp Jun 26 '13 at 08:13
  • removing the `r` from the Proxy type fixes the kind, but then gives another about an illegal instance declaration – ajp Jun 26 '13 at 08:27
  • 1
    @ajp You need to add the following two language extensions to the top of the file: `{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}` – Gabriella Gonzalez Jun 26 '13 at 15:50
  • 1
    that wasn't quite enough in my case. I ended up needing MultiParamTypeClasses, FlexibleInstances, and UndecidableInstances to get it working. – ajp Jun 27 '13 at 19:49