I have two functions, one with a MonadState constraint of the wrapped type, the other has a MonadState constraint of the unwrapped type. I'd like to seamlessly run the second function within the first.
For example:
import qualified Control.Monad.State.Strict as MTL
import Data.Monoid (Sum)
import Control.Lens.Zoom (zoom)
import Control.Lens.Wrapped (_Wrapped')
outer :: (MTL.MonadState (Sum Int) m) => m Int
outer = zoom _Wrapped' inner
inner :: (MTL.MonadState Int m) => m Int
inner = MTL.get
The above seems to me like it should work, yet I get 3 type checker errors. The first:
Could not deduce (Control.Lens.Zoom.Zoom m0 m Int (Sum Int))
arising from a use of ‘zoom’
from the context (MTL.MonadState (Sum Int) m)
bound by the type signature for
outer :: MTL.MonadState (Sum Int) m => m Int
The type variable ‘m0’ is ambiguous
From my searching, I get the impression that zoom can't do what I want. (found this quote on http://ircbrowse.net/browse/haskell "reltuk: yeah, thats the unfortunate downside of lenses is that zooming forces you to a concrete state monad") I guess that lines up with the error message stating that "m0 is ambiguous".
I'd really rather not change my MonadState constraint into a concrete monad.
Is there some other standard way of doing what I want?
Edit:
This will not type check:
sumOuter :: (Functor (Zoomed m Int),
Zoom m m Int t,
Wrapped t,
Unwrapped t ~ Int,
MTL.MonadState (Sum Int) m) => m Int
sumOuter = zoom _Wrapped' sumInner
sumInner :: (MTL.MonadState Int m) => m Int
sumInner = MTL.get
zoomhas its own class for overloading, so no wonder justMonadStatedoesn't cut it. TheZoomclass covers roughly the same ground asmtl, although it has somewhat more complicated machinery. In any case, you're not obligated to program in concrete monads.You can try enabling
NoMonomorphismRestrictionand inferring a type:Now
:t outergivesThis isn't pretty, but it seems to work.
EDIT:
If you really want to specialize to
Sum Intas the outer state, and also want to haveMonadState (Sum Int) nconstraint, this suffices:What about the
MonadStateconstraint? There's no need to write it out, becauseZoom m n s thasMonadState s mandMonadState t nas superclasses.Likewise, the more general
outerfunction already impliesMonadState t n.