跟著 [BYOHC](https://github.com/CindyLinz/BYOHC-Workshop) 做自己的 compiler ，也兩個月了。

目前 [C](https://github.com/CindyLinz/Haskell.js/tree/master/trans) 和 [AlexLu](https://github.com/op8867555/BYOHC-transpiler) 做到 transpiler 。還跟不上。

為了觀察每一步是怎麼 reduce ，近一個月前全部重做，從 LiveScript 移到 [ES2015](https://github.com/caasi/ulc-playground) 上。 interpreter 倚賴 Promise 完成 async 操作，於是 internal functions 可以傳回 Promise 好處理 I/O 。

略讀了 [The Implementation of Functional Programming Languages](https://news.ycombinator.com/item?id=10609960) ， 1987 年流行的作法還是 `[Response] -> [Request]` ，而不是 I/O monad 。前幾天才找到 SPJ 的 [Tackling the awkward squad](http://research.microsoft.com/en-us/um/people/simonpj/papers/marktoberdorf/)，想搞清楚 IO 到底在做什麼。

文中提到 IO 很像 state monad （但不是...），還不明白 GHC 是怎麼做的，只好真的用 state monad 做看看：

```
bind :: IO a -> (a -> IO b) -> IO b
bind = \IOa \f IOa \a \RealWorld pair (f a) RealWorld
```

於是可以把在 `IO a` 中的 `RealWorld` 傳到 `IO b` ，正如 #haskell.tw 上大家形容的那樣：「把 RealWorld 傳下去」。

問題出在中間的 `a -> IO b` 裡面用到的 `return`，把 `b` 變成 `IO b` 的是它，於是它需要知道 `IO a` 中的 `RealWorld` 是什麼東西（當然要是我可以把 `RealWorld` 變不見，又能留下它造成的效果最好，可是我還不懂該怎麼做）。

untyped lambda calculus 中沒有 type class 可用，我又不是用 env 實作 interpreter ，最好只好把 `bind` 的 type 改成：

```
bind :: IO a -> ((b -> IO b) -> a -> IO b) -> IO b
```

那個 `b -> IO b` 就是 `return` 。（讓我想起 Angular.js 的 dependency injection ）

看 [How to desugar Haskell code](http://www.haskellforall.com/2014/10/how-to-desugar-haskell-code.html) 說 type class 在 desugar 後會直接呼叫對的 function ，應該不用像我這樣亂改 type 。

接下來沒有 haskell-src-exts 跟 haskell-src 可以用，該怎麼做才好？

---

這次學到兩件事，一是傻傻找 left-most out-most 的效能有多慘，現在 playground 沒有 delay ，每步都用 requestAnimationFrame ，也要好久才能把讀進去的字串吐出來。難怪那麼多論文都在講，怎麼有效率地 reduce 。二是對 pure functional language 來說，時間順序不重要，只有在和困在時間中的人類互動時，才需要考慮這點。

欸，中二病又發了，快去睡覺比較實在。

