Re: Build Your Own Haskell Compiler #1.3
haskell-src-exts 的 AST 複雜很多,會遇到放在 Maybe 和 [] 裡面的 AST 。這時要是只用 famp ,就會遇上把 [Term a] 變成 [Desugar (Term a)] 這種窘境。真正想得到的是 Desugar [Term a] ,接著才可以繼續 (<*>) 下去。
先把本來的 Term 改成這樣:
data Term a = Var a
| Lam [a] (Term a)
| App (Term a) [Term a]
deriving (Show)表示現在 Lam 可以吃多個變數。(我知道這樣不對,畢竟有 currying 就好了,但為了練習就... XD)
desugar 函數就變成:
instance Desugarable Desugar (Term a) where
desugar (Var a) = Var <$> pure a
desugar (Lam aList term) = Lam <$> traverse pure aList <*> desugar term
desugar (App term termList) = App <$> desugar term <*> traverse desugar termListincrease
在這個練習中,我給自己的目標是算出 term 的數量,於是得增加 Lam <$> traverse pure aList <*> desugar term 生出來的 Desugar (Term a) 中的 info 。
為了可以這樣寫:
desugar (Lam aList term) = do
increase 1
Lam <$> traverse pure aList <*> desugar termm就得做出這樣的函數:
increase :: Int -> Desugar ()
increase i = D (i, ()) :: Desugar ()當兩個 Desugar a 被 (>>=) 接在一起時,得把 tuple 的後面那項送給 monad 使用者,再將得出的結果中的 info (第一項)加在一起計數,做出新的 Desugar a :
instance Monad Desugar where
return = pure
D (info, a) >>= f =
let
D (info', a') = f a
in
D (info + info', a')Monad Laws
最後檢查一下這個 monad 有沒有遵守 monad laws :
return a >>= f = f a -- left identity
m >>= return = m -- right identity
(m >>= f) >>= g = m >>= (\x -> f x >>= g) -- associativity在 left identity law 中, return a 得到的 info 是 0 ,不影響 f a 的結果。
在 right identity law 中, m 帶的 info 會和 return 帶來的 0 加在一起,一樣不影響 m 。
在 associativity law 中,先完成 m >>= f 會把 m 和 f 帶來的 info 先加在一起,再加上 g 帶來的 info ;而等號右邊,會加把 f 和 g 帶來的 info 相加,再加上 m 的, + 自己就有結合律,故此 monad 也有。
拖了三個月。這段時間斷斷續續讀著 Haskell Programming from First Principle ,大概讀了四分之一。 haskell-src-exts 在這之中升到了 0.18 版,現在只有 Annotated AST ,還補上了一些 type 。十月初試著升級看看,沒什麼困難,就是打字罷了。剛發現已經到了 0.19 版,不知道又改了些什麼?
前途茫茫,越來越在意自己沒有扎實的電腦科學基礎。之前被推薦過 coursera 上的 Programming Languages, Part A ,也許是個起點。