如何将缩放与新类型的 MonadState 约束一起使用?
How do I use zoom with a MonadState constraint of a newtype?
我有两个函数,一个具有包装类型的 MonadState 约束,另一个具有未包装类型的 MonadState 约束。我想无缝 运行 第一个功能中的第二个功能。
例如:
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
以上在我看来应该可行,但我收到 3 个类型检查器错误。第一个:
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
根据我的搜索,我的印象是 zoom
不能做我想做的事。 (在 http://ircbrowse.net/browse/haskell "reltuk: yeah, thats the unfortunate downside of lenses is that zooming forces you to a concrete state monad" 上找到了这句话)我猜这与错误消息一致,指出 "m0 is ambiguous".
我真的不想将我的 MonadState 约束更改为具体的 monad。
有没有其他标准方法可以做我想做的事?
编辑:
这不会进行类型检查:
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
有自己的 class 用于重载,所以难怪 MonadState
不削减它。 Zoom
class 涵盖与 mtl
大致相同的领域,尽管它的机制稍微复杂一些。在任何情况下,您都没有义务使用具体的 monad 进行编程。
您可以尝试启用 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
作为 superclass 。
同样,更一般的 outer
函数已经暗示了 MonadState t n
。
我有两个函数,一个具有包装类型的 MonadState 约束,另一个具有未包装类型的 MonadState 约束。我想无缝 运行 第一个功能中的第二个功能。
例如:
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
以上在我看来应该可行,但我收到 3 个类型检查器错误。第一个:
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
根据我的搜索,我的印象是 zoom
不能做我想做的事。 (在 http://ircbrowse.net/browse/haskell "reltuk: yeah, thats the unfortunate downside of lenses is that zooming forces you to a concrete state monad" 上找到了这句话)我猜这与错误消息一致,指出 "m0 is ambiguous".
我真的不想将我的 MonadState 约束更改为具体的 monad。
有没有其他标准方法可以做我想做的事?
编辑:
这不会进行类型检查:
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
有自己的 class 用于重载,所以难怪 MonadState
不削减它。 Zoom
class 涵盖与 mtl
大致相同的领域,尽管它的机制稍微复杂一些。在任何情况下,您都没有义务使用具体的 monad 进行编程。
您可以尝试启用 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
作为 superclass 。
同样,更一般的 outer
函数已经暗示了 MonadState t n
。