# 星之一角

What have you found for these years?

## 2009-11-01

updated 2009-11-07 23:13:

*

data Tem = Txt String | Var Tem deriving Show
type Env = [(String, String)]

lookupVar :: String -> Env -> Maybe String
lookupVar = lookup

resolve :: Tem -> Reader Env String
resolve (Txt str) = return str

`resolve (Var tem) = do                       name <- resolve tem                       val  <- asks (lookupVar name)                       return (maybe "" id val)`

`resolve (Var tem) = resolve tem >>= \name -> asks (lookupVar name)                                >>= \val  -> return (maybe "" id val)resolve (Var tem) = resolve tem >>= \name -> (ask >>= \env -> return (lookupVar name env))                                >>= \val  -> return (maybe "" id val)`

`instance Monad (Reader e) where     return a         = Reader \$ \e -> a     (Reader r) >>= f = Reader \$ \e -> f (r e) e`

#### 4 retries:

jinjing said...

scm said...

e 有餵給 f 呀。在 Reader 定義的第二行:

(Reader r) >>= f = Reader \$ \e -> f (r e) e

e 不就是 f 的第二個參數嗎？

r >>= f = \e -> f (r e) e

r 已經是一個型別是 e -> a 的函數了，而 f 是 a -> (e -> b). 等號右邊必須是一個 e -> b, 那顯然做法就是先把環境餵給 r 產生一個 a, 然後給 f, 得到一個 e -> b. 最後還要把環境再餵給 f (r e) 一次，才能得到 b.

scm said...

ask 可以把環境取出來，它的型別是 e -> e. 怎麼做呢？就用 ask = id 就可以了。我們把這段程式展開看看：

resolve tem >>= \name ->
(ask >>= \env -> return (lookupVar name env)) >>=
\val -> return (maybe "" id val)

resolve tem >>= \name ->
ask >>= \env ->
lookupVar name env >>= \val ->
return (maybe "" id val)

resolve tem >>= \name ->
F name

\e -> (\name -> ask >>= F name) (resolve tem e) e

\e -> (ask >>= F (resolve tem e)) e

\e -> (\e -> F (resolve tem e) (ask e) e) e
= \e -> F (resolve tem e) (ask e) e

ask 的任務是把 e 取出來，而我們知道 ask 就只是 identity function. 化簡成

\e -> F (resolve tem e) (ask e) e
= \e -> (\env -> lookupVar ...) (ask e) e
= \e -> (\env -> lookupVar ...) e e

F 就這樣得到 e 了。其實他得到兩個 e. 第一個是 ask 的結果，剛好是 e. 第二個是要接著往下面傳的 e, F 不會直接去動它。

godfat 真常 said...

> jinjing

> scm