カリー化ふたたび
以前に書いたセミナーの振り返り(カリー化、部分適用、その他の話題 - Life Goes On)について、通勤電車でつらつら考えていて、小さいラムダ式と大きいラムダ式を区別するには、モナドなし/あり2つの Arrow を使えばいいんじゃないかと思いました。
つまりこんなコード。
g :: (Int, Int, Int) -> IO Int g (a,b,x) = return (a*x+b) g' :: (Int, Int) -> IO (Int -> Int) g' (a,b) = return (\ x -> a*x+b) g'' :: Int -> IO (Int -> Int -> Int) g'' a = return (\ b x -> a*x+b) g''' :: IO (Int -> Int -> Int -> Int) g''' = return (\ a b x -> a*x+b) main = do g0 <- g (3,5,7) print $ g0 g1 <- g' (3,5) print $ g1 7 g2 <- g'' 3 print $ g2 5 7 g3 <- g''' print $ g3 3 5 7
*Main> main 26 26 26 26
これなら g^^ と g^^^ も区別できるし、整合性はとれてるような気がします。そんな形式の話より、意味が大事なんだとは思うのですが。
あと、g^^^ を評価する実行エンジン(E)が何回か出てきますが、それぞれ数学的に違う型だというのは、理解しました。
でも実装に落ちると、いちばん外側の引数を固定化するという意味で、同じ実行エンジンが使える(逆に区別できない)ような気がします。
今度、聞いてみよう。
(それにしても我ながらしつこいなー)