@wx_y_am
http://tieba.baidu.com/p/4167457985
有點偏題,還是發這裏吧
圖也搬過來

這個叫 hy,算是 lisp 的方言
http://docs.hylang.org/en/latest/
簡單說就是通過 python 的 import hook,可以運行前將 hy 代碼編譯成 cpython 的 AST,然後再通過 python 本身編譯成 python bytecode 運行。由於在 AST 層級操作,所以提供完整的 macro 支持(當然不是 scheme 的 hygiene)。
可以和 python 無縫結合,即如果安裝了 hy,在 pyhton 裏可以直接 import 用 hy 寫的東西,反過 hy 也可以 import 任何 python 的。
我正在用 hy 寫一個 monad 庫,這是其中一個例子,那時候剛好在測試就截圖了。
這個 gcd 不一樣的地方是,算法是普通的輾轉相除取餘,但整個 gcd 返回的是個 writer monad。也就是 gcd 的 signature (用 haskell 風格描述)是 gcd :: int -> int -> StringWriter string int。其中 StringWriter string 是 writer monad,string 是 monoid。

我另外將相關代碼部分截了圖,左欄是 writer monad 和 execute, tell 的實現,功能和 haskell 的 execWriter, tell 一樣,只不過我利用了 python 的動態類型特性。tell 是將 message 添加到 writer 的累積部分(tuple (result, messages) 的第二部分),execute 是進行這個 writer 運算並將第二部返回,即累積的 message,也就是每次遞歸中 gcd 裏 tell 發送的內容。最後用 print 輸出。
中間是 do-monad 和 do-monad-m 這兩個 macro 的實現,用起來類似 haskell 的 do notation。用來方便寫 monad comprehension。do-monad 和 do-monad-m 的區別是前者會自動增加個 m-return (haskell 裏的 return)call 到結果。所以因爲 gcd 返回的就是 monad,if 的 else 部分遞歸的時候就要用 do-monad-m。
它們和 clojure 的 domonad 類似,不過 clojure 的 monad 不是 boxed 的,而我因爲想在 python 裏支持 >> 作爲 bind(操作符重載),而使用了 class 實現。壞處是這樣寫一些 higher kind 的 monad 很繞,好處是我可以通過附帶的訊息,寫出不需要註明 arity 的 lift 函數。
右上是 monad 的 base class,提供了一些通用操作,其中 join, fmap 和 bind 是相互遞歸的,必須在 subclass 中實現 bind 或者 join, fmap,否則無法直接用。
右下是第一個截圖的 gcd.hy 源碼,方便對應。
這個庫除了 writer,我還實現了 identity, maybe, either, reader, state, continuation,正在整理測試和文檔,弄好了就發出去。
http://tieba.baidu.com/p/4167457985
有點偏題,還是發這裏吧
圖也搬過來

這個叫 hy,算是 lisp 的方言
http://docs.hylang.org/en/latest/
簡單說就是通過 python 的 import hook,可以運行前將 hy 代碼編譯成 cpython 的 AST,然後再通過 python 本身編譯成 python bytecode 運行。由於在 AST 層級操作,所以提供完整的 macro 支持(當然不是 scheme 的 hygiene)。
可以和 python 無縫結合,即如果安裝了 hy,在 pyhton 裏可以直接 import 用 hy 寫的東西,反過 hy 也可以 import 任何 python 的。
我正在用 hy 寫一個 monad 庫,這是其中一個例子,那時候剛好在測試就截圖了。
這個 gcd 不一樣的地方是,算法是普通的輾轉相除取餘,但整個 gcd 返回的是個 writer monad。也就是 gcd 的 signature (用 haskell 風格描述)是 gcd :: int -> int -> StringWriter string int。其中 StringWriter string 是 writer monad,string 是 monoid。

我另外將相關代碼部分截了圖,左欄是 writer monad 和 execute, tell 的實現,功能和 haskell 的 execWriter, tell 一樣,只不過我利用了 python 的動態類型特性。tell 是將 message 添加到 writer 的累積部分(tuple (result, messages) 的第二部分),execute 是進行這個 writer 運算並將第二部返回,即累積的 message,也就是每次遞歸中 gcd 裏 tell 發送的內容。最後用 print 輸出。
中間是 do-monad 和 do-monad-m 這兩個 macro 的實現,用起來類似 haskell 的 do notation。用來方便寫 monad comprehension。do-monad 和 do-monad-m 的區別是前者會自動增加個 m-return (haskell 裏的 return)call 到結果。所以因爲 gcd 返回的就是 monad,if 的 else 部分遞歸的時候就要用 do-monad-m。
它們和 clojure 的 domonad 類似,不過 clojure 的 monad 不是 boxed 的,而我因爲想在 python 裏支持 >> 作爲 bind(操作符重載),而使用了 class 實現。壞處是這樣寫一些 higher kind 的 monad 很繞,好處是我可以通過附帶的訊息,寫出不需要註明 arity 的 lift 函數。
右上是 monad 的 base class,提供了一些通用操作,其中 join, fmap 和 bind 是相互遞歸的,必須在 subclass 中實現 bind 或者 join, fmap,否則無法直接用。
右下是第一個截圖的 gcd.hy 源碼,方便對應。
這個庫除了 writer,我還實現了 identity, maybe, either, reader, state, continuation,正在整理測試和文檔,弄好了就發出去。





