【发布时间】:2020-05-24 06:52:02
【问题描述】:
作为 Haskell 自学练习的一部分,我正在尝试为我的类型派生一个 Monad 实例。类型定义为:
newtype ParsePackUnpack f a = ParsePackUnpack
{
unparse:: State PackUnpackState (Ap f a)
}
其中Ap f a 来自Data.Monoid。对于我的类型,我想说解析是一个有状态的操作,结果是任何monoid。
到目前为止,我已经通过提升成功实现了这个 3 级深度类型的 Functor 和 Applicative 实例:
instance Functor f => Functor (ParsePackUnpack f) where
fmap f ma =
let f' = fmap f -- lift (a -> b) to (Ap f a -> Ap f b)
in ParsePackUnpack $ f' <$> (unparse ma)
instance Applicative f => Applicative (ParsePackUnpack f) where
pure = ParsePackUnpack . pure . pure
f <*> ma =
let f' = liftA2 (<*>) . unparse $ f -- lift Ap f (a -> b) -> Ap f a -> Ap f b to State s (Ap f a) -> State s (Ap f b)
in ParsePackUnpack $ f' (unparse ma) -- Apply to State s (Ap f a)
但我无法为我的类型正确派生 Monad 实例。经过一番打高尔夫球后,这是我的最新尝试:
instance Monad f => Monad (ParsePackUnpack f) where
return = ParsePackUnpack . return . return
ma >>= f = ParsePackUnpack . state $ \st ->
let (a, s) = runState (unparse ma) st
res = a >>= fst . flip runState s . unparse . f -- fst ignores state from the result
in (res, s)
我认为这是不正确的,因为我忽略了 res 操作中的状态。
为我的类型实现>>= 操作的正确方法是什么?由于这是一个学习练习,我试图避免使用 Monad 变压器。如果 Monad 变压器是要走的路,你能解释一下为什么会这样吗?
【问题讨论】:
标签: haskell monads state-monad