動機
state monad是left 2 right,對應到iteration (左遞迴) reverse state monad是right 2 left,對應到recursion (右遞迴)
derive state monad
轉成iteration
def s(l):
if not l:
return 0
else:
return l[0] + s(l[1:])
def s2(l, acc=0):
if not l:
return acc
else:
return s2(l[1:], l[0] + acc)
把acc往下推
def s3(l):
if not l:
return lambda acc: acc
else:
return lambda acc: s3(l[1:])(l[0] + acc)
用成類似monad的樣子
def ret(acc):
return acc
def bind(mx, f):
return lambda acc: mx(f(acc))
def s4(l):
if not l:
#return ret(0)
return ret
else:
return bind(s4(l[1:]), lambda acc: l[0] + acc)
def s2(l, acc=0):
if not l:
return acc
else:
return s2(l[1:], l[0] + acc)
到s4其實就推的差不多了,但是ret其實不符合monad的return定義 所以我們改一下
real state monad
def ret2(acc):
return lambda ignored_acc: acc
def bind2(mx, f):
return lambda acc: f(mx(acc))
def s5(l):
if not l:
return ret2(0)
else:
return bind2(s5(l[1:]), lambda acc: l[0] + acc)
def s(l):
if not l:
return 0
else:
return l[0] + s(l[1:])
如果去走一下整個過程會發現他與遞迴版的很像,因為0是從底部給,不像之前是依靠外面給
state monad
state monad其實就是會留一層acc在外層等人給 剩下就是找順序來,所以是left 2 right
newtype State s a = State { runState :: s -> (a,s) }
instance Functor (State s) where
(<$>) :: (a -> b) -> State s a -> State s b
(<$>) fn (State sa) = State (\s0 -> let (a, s1) = sa s0 in (fn a, s1))
instance Applicative (State s) where
pure :: a -> State s a
pure a = State (\s -> (a,s))
(<*>) :: State s (a -> b) -> State s a -> State s b
(<*>) (State sa) (State sb) =
State (\s0 -> let (fn, s1) = sa s0
(a, s2) = sb s1
in (fn a, s2))
instance Monad (State s) where
(>>=) :: State s a -> (a -> State s b) -> State s b
(>>=) (State sa) fn =
State (\s0 -> let (a, s1) = sa s0 -- 先往下遞迴
State sb = fn a -- 拿到的往f灌
in sb s1) -- 接回去
reverse state monad
reverse的話就是先往右手邊遞迴,做出right 2 left的效果
instance Applicative (ReverseState s) where
pure x = ReverseState $ (,) x
mf <*> mx =
ReverseState $ \s ->
let (x, future) = runReverseState mx s -- 先往右遞迴
(f, now) = runReverseState mf future -- 終於回來了,用前面的值灌回來
in (f x, now)
如果用與前面一樣的想法(先做右邊),去設計monad 會遇到一個問題
我們只有f要怎麼右遞迴
instance Monad (ReverseState s) where
mx >>= f =
ReverseState $ \s ->
let (b, future) = runReverseState ?? s
(a, now) = runReverseState mx future
in (b, now)
- 我們目前的值,其實是在mx之中,所以要想方法拿到mx裡面的值
- 要拿mx的值要透過runReverseState
- 不是已經call過了嗎
(a, now) = runReverseState mx future
所以把這個值餵回去f就好了
instance Monad (ReverseState s) where
mx >>= f =
ReverseState $ \s ->
let (b, future) = runReverseState (f a) s
(a, now) = runReverseState mx future
in (b, now)
Q: 怎麼可能有futrue又有a,這樣不是互相依賴嗎? A: haskell是lazy的
Ref
The Curious Time-Traveling Reverse State Monad You Could Have Invented The State Monad