状态单子绑定
State Monad Bind
我想我了解 State Monad 的工作原理。我已经设法编写了一些使用 State Monad 的代码。
我了解 State 的 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 将 do 表示法转换为函数。
您需要使用 (>>)
而不是 (>>=)
:
runState (statefulComputation1 >> (enterClub "Manuel") >> leaveClub) []
(enterClub "Manuel")
具有类型 State PeopleStack String
而 (>>=)
需要函数 String -> State PeopleStack a
作为其第二个参数。由于您不使用 statefulComputation1
的结果,您可以将它们与 (>>)
结合使用,这会忽略第一个状态计算的结果。
绑定运算符 (>>=) 右侧的每个项目都需要是 lambda ....,所以这可行
runState (statefulComputation1 >>= \_ -> enterClub "Manuel" >>= \_ -> leaveClub) []
或者,您可以使用 shorthand (>>)
runState (statefulComputation1 >> enterClub "Manuel" >> leaveClub) []
我想我了解 State Monad 的工作原理。我已经设法编写了一些使用 State Monad 的代码。
我了解 State 的 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 将 do 表示法转换为函数。
您需要使用 (>>)
而不是 (>>=)
:
runState (statefulComputation1 >> (enterClub "Manuel") >> leaveClub) []
(enterClub "Manuel")
具有类型 State PeopleStack String
而 (>>=)
需要函数 String -> State PeopleStack a
作为其第二个参数。由于您不使用 statefulComputation1
的结果,您可以将它们与 (>>)
结合使用,这会忽略第一个状态计算的结果。
绑定运算符 (>>=) 右侧的每个项目都需要是 lambda ....,所以这可行
runState (statefulComputation1 >>= \_ -> enterClub "Manuel" >>= \_ -> leaveClub) []
或者,您可以使用 shorthand (>>)
runState (statefulComputation1 >> enterClub "Manuel" >> leaveClub) []