【问题标题】:How to implement the MonadState class without using record syntax?如何在不使用记录语法的情况下实现 MonadState 类?
【发布时间】:2013-05-13 13:02:23
【问题描述】:

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

【问题讨论】:

  • 问题是你这里没有真正有状态的数据类型,所以你不能实现一个有意义的MonadState实例。学习如何为特定类实现“只是一些实例”没有什么意义,您更想做的是设计一种数据类型以适应各种类的要求。或者,你为某个问题设计了一个数据类型,突然注意到“嘿,这个东西的行为很像State monad。也许它应该是MonadState 的一个实例”? – 通常情况下,Monad* 类不需要这样做,只需使用合适的转换器堆栈即可。
  • newtype Foo s a = Foo (s -> (s, a))开头。

标签: haskell monads ghc monad-transformers state-monad


【解决方案1】:

让我们从 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

所以我们得到一个新状态,将它输入到我们现有的状态单子中,然后将结果值/状态对传递给 g 并返回结果。

这和记录语法之间的差异总数只是我必须手动定义unwrap

完成我们的单子

runState = unwrap

get = MyState \s -> (s, s)
put a = MyState \s -> (a, ())

【讨论】:

  • 我见过几乎所有使用数据类型实现 MonadState 的示例,该数据类型实际上是 (s -> (s, a)) 类型函数的包装器。能不能去掉内层函数?
  • 不是真的,状态单子差不多就是这样。
  • @jozefg 我认为应该是:in newF newState 而不是 in newF state 在您的绑定定义中
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-29
  • 2018-06-29
  • 1970-01-01
  • 2021-04-20
  • 1970-01-01
  • 2019-12-23
  • 1970-01-01
相关资源
最近更新 更多