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
zoom
has its own class for overloading, so no wonder justMonadState
doesn't cut it. TheZoom
class 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
NoMonomorphismRestriction
and inferring a type:Now
:t outer
givesThis isn't pretty, but it seems to work.
EDIT:
If you really want to specialize to
Sum Int
as the outer state, and also want to haveMonadState (Sum Int) n
constraint, this suffices:What about the
MonadState
constraint? There's no need to write it out, becauseZoom m n s t
hasMonadState s m
andMonadState t n
as superclasses.Likewise, the more general
outer
function already impliesMonadState t n
.