我正在尝试为这样一种类型实现应用实例:
newtype State s a = State {runState :: s -> (a, s)}
对于(<*>)函数,我有一些不同的想法。我想到的一个实现方法是:
(<*>) :: State s (a -> b) -> State s a -> State s b
State f <*> State s = State $ do
(fa, fs) <- f
let (sa, ss) = s fs
return (fa sa, ss)
或者
(<*>) :: State s (a -> b) -> State s a -> State s b
State f <*> State s = State $ do
(sa, ss) <- s
let (fa, fs) = f ss
return (fa sa, fs)
哪一个(或它们中的任何一个)是正确的,为什么?
它们都可以通过类型检查,只是“状态”转换顺序不同。我找不到任何好的理由来推荐其中一个而不是另一个...
>>=
定义,适用于像State
一样的单子,让你思考:State f >>= g = State $ \s -> let { (u, x) = f t; (t, y) = runState (g x) s } in (u, y)
。注意x
,y
从上到下,但s
,t
,u
从下到上。这仍然让我的大脑感到疼痛 :) - Benjamin Hodgsondo
块都在“函数”单子中。当且仅当f :: a -> b
对于某些a, b
时,do { z <- f; y <- g; return (z y) } = \x -> let {z = f x; y = g x } in (const $ z y) x
。(只是为了使 下面的这条评论 更容易被注意到)。 - Will Ness