-
Notifications
You must be signed in to change notification settings - Fork 22
Description
Some libraries, like lens, provide functions that are meant for use in MTL transformer stacks. Example:
http://hackage.haskell.org/package/lens-4.17/docs/Control-Lens-Setter.html#g:5
If Eff had an instance for MonadState, then I could use those Lens functions without having to rewrite them using the put and get from Control.Monad.Freer.State - it would happen automatically.
I have spent a number of days on this, but my instance manipulation skills are not the greatest, so I ended up with something like this:
instance MTL.MonadState s (Eff (State s ': effs)) where
get = get
put = put
instance {-# OVERLAPPABLE #-} MTL.MonadState s (Eff effs) => MTL.MonadState s (Eff (eff ': effs)) where
get = MTL.get
put = MTL.put
-- single actions that uses MTL and Eff values together without wrapping/unwrapping newtypes
action :: Eff (State Bool ': effs) ()
action = do
b <- MTL.get
put $ not b
ranAction :: Eff effs ((), Bool)
ranAction = runState True actionI also tried a solution involves defining an instance for a newtype wrapping Eff and using the constraints library to unsafely deduce MonadState s (Eff effs) from Member (State s) effs, but I had to use explicit TypeApplication to get it to work. I can post the code for that if you think that avenue is more likely where you would want to go with this.
A third possibility would be using something from the reflection package to provide the instance at runtime, but I haven't explored that.
I have only been playing around with
TL;DR: I don't know the best way to do this, but I think this library can provide something helpful for this use case.