首页 文章

State Monad Bind

提问于
浏览
1

我想我理解State Monad是如何运作的 . 我设法写了一些使用State Monad的代码 .

我理解Monad的国家实例如何运作:

instance Monad (State s) where  
return x = State $ \s -> (x,s)  
(State h) >>= f = State $ \s -> let (a, newState) = h s  
                                    (State g) = f a  
                                in  g newState

这段代码非常好用:

type PeopleStack = [String]

enterClub :: String -> State PeopleStack String
enterClub name = state $ \xs -> (name ++ " entered club", name:xs)

leaveClub :: State PeopleStack String
leaveClub = state $ \(x:xs) -> ("Someone left the club", xs)

clubAction :: State PeopleStack String
clubAction = do
  enterClub "Jose"
  enterClub "Thais"
  leaveClub
  enterClub "Manuel"

但是当我尝试在绑定函数中编写clubAction时,我似乎无法使其工作 .

这是我试过的:

let statefulComputation1 = enterClub "Jose"
statefulComputation1 :: State PeopleStack String

runState (statefulComputation1 >>= (enterClub "Manuel") >>= leaveClub) []

我收到此错误:

<interactive>:13:22:
Couldn't match type ‘StateT
                       PeopleStack Data.Functor.Identity.Identity String’
               with ‘String
                     -> StateT PeopleStack Data.Functor.Identity.Identity a’
Expected type: String
               -> StateT PeopleStack Data.Functor.Identity.Identity a
  Actual type: State PeopleStack String
Relevant bindings include
  it :: (a, PeopleStack) (bound at <interactive>:13:1)
In the second argument of ‘(>>=)’, namely ‘leaveClub’
In the first argument of ‘runState’, namely
  ‘(state1 >>= leaveClub)’

我的问题是我如何使用bind将该表示法转换为函数 .

2 回答

  • 3

    绑定运算符(>> =)右侧的每个项都需要是一个lambda ....,这样就行了

    runState (statefulComputation1 >>= \_ -> enterClub "Manuel" >>= \_ -> leaveClub) []
    

    或者,你可以用速记 (>>)

    runState (statefulComputation1 >> enterClub "Manuel" >> leaveClub) []
    
  • 2

    您需要使用 (>>) 而不是 (>>=)

    runState (statefulComputation1 >> (enterClub "Manuel") >> leaveClub) []
    

    (enterClub "Manuel") 的类型为 State PeopleStack String ,而 (>>=) 需要函数 String -> State PeopleStack a 作为其第二个参数 . 由于您不使用 statefulComputation1 的结果,您可以将它们与 (>>) 组合,忽略第一个状态计算的结果 .

相关问题