Wes*_*sey 0 monads haskell state-monad
我是Monads和Haskell的新手,并试图了解如何在使用它们时返回值.我的代码如下所示:
foo :: A -> B
foo a = do b <- fooC a (C 0)
-- want to return just (B "b")
fooC :: A -> C -> State MyState B
fooC a c = return (B "b")
Run Code Online (Sandbox Code Playgroud)
我试过用snd (snd b)
,但显然State MyState B
不是一个元组?如何返回所需的值(B "b")
?
编辑:考虑到丹尼尔的建议,重写如下:
data MyState = MyState String
data C = C Int
foo :: String -> String
-- want to return just "b"
foo a = evalState (fooC a) (C 0)
fooC :: String -> Int -> State MyState String
fooC a c = return "b"
Run Code Online (Sandbox Code Playgroud)
这仍然会导致编译错误:
Couldn't match expected type `State s0 String'
with actual type `Int -> State MyState String'
In the return type of a call of `fooC'
Probable cause: `fooC' is applied to too few arguments
In the first argument of `evalState', namely `(fooC a)'
In the expression: evalState (fooC a) (C 0)
Run Code Online (Sandbox Code Playgroud)
编辑2:修复!最终版本如下:
import Control.Monad.State
data MyState = MyState String
data C = C Int
foo :: String -> String
-- want to return just (B "b")
foo a = evalState (fooC a (C 0)) (MyState "whatever")
fooC :: String -> C -> State MyState String
fooC a c = return "b"
main = print(foo("test"))
-- prints "b"
Run Code Online (Sandbox Code Playgroud)
你需要的是什么
foo a = evalState (fooC a (C 0)) (MyState "whatever")
Run Code Online (Sandbox Code Playgroud)
您构造State MyState B
操作fooC a (C 0)
,解包它以获取函数,并将该函数应用于初始状态.由于在此示例中未使用状态,因此您可以在此处使用undefined
而不是MyState "whatever"
,但通常,您需要提供有意义的初始状态.
State MyState B
它不是一个元组,它与函数同构
MyState -> (B, MyState)
Run Code Online (Sandbox Code Playgroud)
但是该函数包含在a中newtype
(详细信息因monad变换器库包和版本而异),因此要访问应用于初始状态的该函数的结果,需要一个展开函数.因为State
,有
runState :: State s r -> (s -> (r,s))
Run Code Online (Sandbox Code Playgroud)
它给你返回对的功能,
evalState :: State s r -> (s -> r)
Run Code Online (Sandbox Code Playgroud)
它为你提供了由函数组成的函数fst
,因此最终状态被丢弃了
execState :: State s r -> (s -> s)
Run Code Online (Sandbox Code Playgroud)
组成函数snd
,所以只返回最终状态.