もう一回
今度はCPS(Continuation Passing Style)使って書いてみましょうというお話。
正直なところ
http://pllab.is.ocha.ac.jp/~asai/papers/contfest08slide.pdf
Continuation Festa 08でもあったTyping Printfみた方が良いです。
元のMLのを見てみると
例えば
fun lit x k s = k (s ^ x)
において、xは文字列リテラルとして扱いたい引数、kがcontinuation、sはここまでで累積された文字列を表しているようですが、CPS使うんだったらsとかいらねーんじゃ無いかと思って私が適当にでっち上げたのがこれ
lit :: String -> (String -> a) -> a lit x cont = cont x int :: (String -> a) -> Int -> a int cont x = cont $ show (x::Int) str :: (String -> a) -> String -> a str cont x = cont x oo p1 p2 cont = p1 (\x -> p2 (\y -> cont (x ++ y))) printf pattern = pattern id
とかこんなんで
printf (int `oo` lit "/" `oo` int) 1 2 "1/2" printf (int `oo` lit " is " `oo` str) 1 "one" "1 is one"
出来ました。
当然コンパイル時にerrorも吐いてくれます
main = putStrLn $ printf (int `oo` str `oo` int `oo` str) 1 2 3 4 No instance for (Num String) arising from the literal `2' at impl3.hs:17:60 Possible fix: add an instance declaration for (Num String) In the third argument of `printf', namely `2' In the second argument of `($)', namely `printf (int `oo` str `oo` int `oo` str) 1 2 3 4' In the expression: putStrLn $ printf (int `oo` str `oo` int `oo` str) 1 2 3 4