Reader Monad (3)
有點不專心地決定 Reader Monad 差不多可以了 @@"
說是有點不專心是因為沒有實際演練,而且一直同時在做別的事。
有時候會覺得 inspect 有沒有懂這件事,並不是那麼容易。
更何況,未來有一天發現之前誤解了一部份的這種事,其實也是常常發生。
所以有時候也確實不用執著於是否完全懂了。
另一方面,後來有種豁然開朗的感覺。不明白之前在不懂什麼。
見樹不見林也是很麻煩的事。發現卡住時,應該要立刻切換角度才對。
非常感謝 jinjing 和 scm 在 Reader Monad (2) 的解釋,
尤其是後者的推衍。唔,也許是我太懶,應該自己手動展開和化簡。
畢竟說來 purely functional 本來就是應該這樣看的不是嗎?
或許是我太執著於希望見林而不願見樹...? 總之大概寫一下目前的心得。
上篇的 comment 中提到我有兩個盲點。
是當時隔天早上搭車時忽然間想到的。
第一點是我忘記了 bind (>>=) 的 type 是:
(>>=) :: (Monad m) => m a -> (a -> m b) -> m b
重點是一開始是 m a, 但後面是 m b,
也就是說 a 和 b 的 type 不見得要一樣。
但在測試的 resolve :: Tem -> Reader Env String 中,
我一直把他想成每一個 bound function 的 return type 都
必須是: `Reader Env String'
然而實際上應該是最後一個 bound function 是就好了。
在這一段時: val <- asks (lookupVar name)
實際上應該是 Reader Env (Maybe String)
也就是說 Reader Monad 中 Reader Env 是不變,
原本的 Env 只會被一直傳下去,似乎沒有去動到他的機會?
r >>= f >>= g
= \e -> f (r e) e >>= g
= \e -> g ((\e -> f (r e) e) e) e
呃,不知道有沒有展開正確,總之這樣看起來 e 確實不會變。
*
第二個盲點是我搞錯 Reader Env String 的 type,
我一直把他想成是擁有兩個值的 data, 類似 pair 那樣。
但實際上 Reader Env String 的 type 應該是 Env -> String.
只要想到這裡就能知道為什麼 ask 在 MonadReader 下就只是 id.
這邊應該會形成一個 Reader Env Env, 因此他的 bound function
才會接收到 env, 而不是原本的 String.
asks 就只是另一個包裝,應該不用額外理解。
*
可能真的是多個 Reader 的 data constructor 就變得比較難懂。
如果是這樣我覺得這說明了兩件事:
1. 雜音確實是會干擾的,再小的雜音都不要小看
2. 我還不熟悉 Haskell 的 Class 和 Instance
也或許是因為物件導向的關係,想到 Class 很容易就想錯邊。
其實這應該也算某種程度的雜音吧...?
==
還不清楚 local 是什麼,晚點看
不過倒是覺得到這裡,monad 真的多懂很多了
3 retries:
> 原本的 Env 只會被一直傳下去,似乎沒有去動到他的機會?
可以的唷,但只能「往下」動。其實這就是你後面提到的 local 的功能。local 的 type 是(e -> e) -> m a -> m a, 其中 e -> e 是改變環境用的函數。在這個程式中:
comp1 >>= \a ->
local f comp2 >= \b ->
comp 3
如果環境是 e, comp1 在 e 的環境下執行。 comp2 收到的環境則是 f e. 而 comp3 的環境又是 e. 這是和 state monad 的不同處, 後者會把 state 串起來。這也是為什麼 reader monad 是 e -> a, state monad 卻得是 s -> (a, s) -- 後者需要把新的 state 傳回來,才能繼續串下去,而新的環境用過就可以丟掉了。
Reader monad 很適合在寫 interpreter 的時候傳環境用。
我在寫 monad 簡介唷。歡迎給意見。
http://www.iis.sinica.edu.tw/~scm/ncs/2009/11/a-monad-primer-1/
下次應該就會用 reader monad 當例子吧。
噢,怪不得叫 local, 還真是直覺? XD
希望這次能一鼓作氣讀完大部份,
不然一放著,之前讀過的東西真的忘記不少 @@"
晚點就拜讀 :D
Post a Comment
Note: Only a member of this blog may post a comment.