我发现我很难理解 MonadState 。
原因可能是大多数示例在其数据结构中混合了记录语法。
因此,我尝试在不使用记录语法的情况下实现 MonadState。
我编写的以下代码确实通过了编译器,但对我来说这完全是无稽之谈。
这些代码有什么问题?
是否有一个不使用记录语法实现 MonadState 的简单示例?
data Foo a b = Foo (Maybe ([a],b)) deriving (Show)
unwrapFoo :: Foo a b -> Maybe ([a],b)
unwrapFoo (Foo x) = x
instance Monad (Foo [a]) where
return x = Foo $ Just ([], x)
m >>= f = case unwrapFoo m of
Just (_, r) -> f r
Nothing -> Foo Nothing
instance MonadState Int (Foo [a]) where
get = Foo $ Just ([], 1)
put _ = Foo $ Just ([],())
*Main> get :: Foo [a] Int
Foo (Just ([],1))
*Main> put 3 :: Foo [a] ()
Foo (Just ([],()))
*Main>
最佳答案
让我们从 State Monad 的基本思想开始。
newtype MyState s a = MyState (s {- current state -}
-> (s {- New state -}, a {- New value -}))
unwrap (MyState f) = f
所以现在我们需要实现 >>=
和 return
。
return
非常简单:
return a = MyState $ \s -> -- Get the new state
(s, a) -- and pack it into our value
换句话说,这只是将当前状态传递给一个新值。
现在>>=
(MyState f) >>= g = MyState $ \state ->
let (newState, val) = f state
MyState newF = g val
in newF state
因此,我们得到一个新状态,将其输入到现有的状态 monad 中,然后将结果值/状态对传递给 g
并返回结果。
此语法与记录语法之间的总差异只是我必须手动定义unwrap
。
完成我们的单子(monad)
runState = unwrap
get = MyState \s -> (s, s)
put a = MyState \s -> (a, ())
关于haskell - 如何在不使用记录语法的情况下实现 MonadState 类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16522744/