Bab*_*ham 2 monads haskell state-monad
我想通过以下函数传递State monad:
e1 :: Int -> (Bool, Int)
e1 el
| el > 100 = (True, el)
| otherwise = (False, 0)
e2 :: Int -> (Bool, Int)
e2 el
| el > 200 = (True, el)
| otherwise = (False, 0)
e3 :: Int -> (Bool, Int)
e3 el
| el > 300 = (True, el)
| otherwise == (False, 0)
implementor :: State Bool Int
implementor = state e1 ...
main = do
print $ runState implementor 10
Run Code Online (Sandbox Code Playgroud)
当前runState传递一个State s a(implementor)和一个值(10),然后从中返回元组e1.
但是,我想将这些操作绑定在一起,例如:
state e1 >>= e2 >>= e3
Run Code Online (Sandbox Code Playgroud)
e1将通过其State Bool Int来e2,这对操作Int(通过el),然后通过它产生State Bool Int于e3其中,再次,将在操作Int中该传入国.
根据本指南,我发现Monad State的实例非常混乱:
instance Monad (State s) where
return :: state $ \s -> (s, a)--this is returning a State which contains function (s -> (s, a))
m >>= k = state $ \s -> let (a, s') = runState m s --?
in runState (k a) s'
Run Code Online (Sandbox Code Playgroud)
我不明白这个bind实例是做什么的,以及如何使用它来绑定e1,e2并e3在一起?
如果使用state :: (s -> (a, s)) -> State s a上e1,你最终得到一个State Int Bool:
state e1 :: State Int Bool
Run Code Online (Sandbox Code Playgroud)
这是在一个状态(在这种情况下是一个Int)上作用的东西,并且在Bool使用该状态时产生一个.所以,如果我们要使用e1,e2并e3经过对方的状态计算,我们可以用使用它们do-notation:
allThree :: State Int ()
allThree = do
firstBool <- state e1
secondBool <- state e2
thirdBool <- state e3
return thirdBool
Run Code Online (Sandbox Code Playgroud)
但是,如果我们忽略前两个Bools,我们可以删除绑定:
allThree :: State Int Bool
allThree = do
state e1
state e2
state e3
Run Code Online (Sandbox Code Playgroud)
现在我们可以do用>>和重写注释>>=.我们结束了
allThree :: State Int Bool
allThree = state e1 >> state e2 >> state e3
Run Code Online (Sandbox Code Playgroud)
至于它是如何工作的,让我们来看看 >>=
m >>= k = state $ \s -> let (a, s') = runState m s
in runState (k a)
Run Code Online (Sandbox Code Playgroud)
而m >> k为m >>= const k.那么让我们检查一下state e1 >> state 2:
state e1 >> state e2
= state e1 >>= const (state e2)
= state $ \s -> let (a, s') = runState (state e1) s in runState (const (state e2) a) s'
-- simplify runState (state e1) s to e1 s
= state $ \s -> let (a, s') = e1 s in runState (const (state e2) a) s'
-- use "const"
= state $ \s -> let (a, s') = e1 s in runState (state e2) s'
-- again simplify runState (state e2) s' to e2 s'
= state $ \s -> let (a, s') = e1 s in e2 s'
Run Code Online (Sandbox Code Playgroud)
因此,以下术语是相同的:
stateful s = runState (state e1 >> state e2) s -- use above to show that
stateless s = let (_, s') = e1 s
in e2 s'
Run Code Online (Sandbox Code Playgroud)
现在,为什么我能使用的变化runState (state f)来f?因为定义State很无聊:
-- simplified, modern versions use a more sophisticated approach!
newtype State s a = State { runState :: s -> (a, s) }
Run Code Online (Sandbox Code Playgroud)
也就是说,一个State完整的动作是一个状态,并返回一个新的状态.因此state功能相当简单:
state :: (s -> (a, s)) -> State s a
state = State
Run Code Online (Sandbox Code Playgroud)
既然runState (State f)是f,runState (state f)也是`f'.
因此,我们可以编写Monad一个稍微不同的实例:
instance Monad (State s) where
(State e1) >>= f = State e3
where
e3 s = let (a, s') = e s
(State e2) = f a
in e2 s'
Run Code Online (Sandbox Code Playgroud)
请记住,>>=期望一个函数可以获取某些内容并返回另一个操作,而 >>可以用于将操作链接到彼此之后.
| 归档时间: |
|
| 查看次数: |
73 次 |
| 最近记录: |