我有两个函数,一个具有包装类型的MonadState约束,另一个具有未包装类型的MonadState约束。我想在第一个函数中无缝运行第二个函数。
例如:
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
上面似乎我觉得应该可行,但我得到3种类型的检查错误。第一个:
zoom
从我的搜索中,我得到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
无法做我想要的印象。 (在http://ircbrowse.net/browse/haskell" reltuk上发现了这个引用:是的,那就是镜头的不幸缺点就是变焦迫使你进入一个具体的状态monad")我想这与错误信息排列在一起表明& #34; m0含糊不清"。
我真的不想将我的MonadState约束改为具体的monad。
还有其他一些标准方法可以做我想要的吗?
这不会输入检查:
handleIntent(intent);
答案 0 :(得分:2)
zoom
有自己的重载类,所以难怪只有MonadState
才能删除它。 Zoom
类涵盖与mtl
大致相同的基础,尽管它有一些更复杂的机制。在任何情况下,您都没有义务在具体的单子中进行编程。
您可以尝试启用NoMonomorphismRestriction
并推断类型:
{-# LANGUAGE NoMonomorphismRestriction #-}
import Control.Lens.Internal.Zoom
import Control.Lens
import Control.Monad.State
import Data.Monoid
import Control.Monad.Except -- for illustration
outer = zoom _Wrapped' get
现在:t outer
给出了
outer ::
(Functor (Zoomed m (Unwrapped t)), Zoom m n (Unwrapped t) t, Wrapped t)
=> n (Unwrapped t)
这不是很漂亮,但似乎有效。
> runState outer (Sum 10)
(10, Sum {getSum = 10})
> runState (runExceptT outer) (Sum 10) :: (Either String Int, Sum Int)
(Right 10,Sum {getSum = 10})
编辑:
如果你真的想专注于Sum Int
作为外部状态,并且想要MonadState (Sum Int) n
约束,那么这就足够了:
sumOuter ::
(Functor (Zoomed m Int), Zoom m n Int (Sum Int)) => n Int
sumOuter = zoom _Wrapped' sumInner
sumInner :: (MTL.MonadState Int m) => m Int
sumInner = MTL.get
MonadState
约束怎么样?没有必要写出来,因为Zoom m n s t
有MonadState s m
和MonadState t n
作为超类。
同样,更通用的outer
函数已经暗示MonadState t n
。