haskell - 如何在不使用记录语法的情况下实现 MonadState 类?

标签 haskell monads ghc monad-transformers state-monad

我发现我很难理解 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/

相关文章:

haskell - 如何在 Haskell 中强制不同类型级别的类型?

haskell - Haskell 中 fromJust 的理由

haskell - 基准过滤器和分区

haskell - UndecidableInstances 何时安全?关于 GHC 扩展的一些一般性问题

haskell - gtksourceview2 : implement completion provider

haskell - 我的 haskell 类型签名不代表该函数

haskell - 数据定义错误haskell

haskell - 解释 GHC 堆配置文件中的悬崖边缘

haskell - 我无法理解维基百科对 "applicative functor"的定义

haskell - 使用 GHC < 8.0 : "phase ` C pre-processor' failed"with "missing binary operator before token " ("" 的 Doctest