如何使用具有newtype的MonadState约束的缩放?

时间:2015-06-14 09:30:53

标签: haskell monad-transformers

我有两个函数,一个具有包装类型的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);

1 个答案:

答案 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 tMonadState s mMonadState t n作为超类。

同样,更通用的outer函数已经暗示MonadState t n