Zenn
😺

カリー化を試す

2025/02/23に公開

Haskellで「標準入力から読み込まれた二行の文字列の数値変換とそれらの加算結果を標準出力へ表示する」という処理を二つのパターンで記述します
文字列を数値変換するケースはよく見かけますが、計算を行うサンプルコードは記憶の中でも一件しか例がないので、試しに作ってみようという趣旨です

main::IO ()
main = putStrLn=<<id=<<(show.sum<$>).
 (<$>((:[]).read<$>getLine))<$>
 (:).read<$>(getLine::IO String)

こちらは配列パターン

main::IO ()
main = (\ [x,y]->((+)<$>x)>>=
 (show<$>).(<$>y).id>>=putStrLn) $
 (map (read<$>)) [getLine,getLine]

この二つのコードはカリー化を応用しています
カリー化とは引数が未適用状態の関数を戻り値に用いるテクニックです
数学では同型対応などと呼ばれます
Haskellでは標準でカリー化をサポートすることで一引数一戻り値の原則を徹底しています
そのおかげで関数を返すコードが書きやすい利点を持ちます
例えば足し算でカリー化を駆使すると以下の通りに書けます

main::IO ()
main=putStrLn.show.($ 1).(+) $ 1

尚冒頭の配列パターンをdoに著すと以下のような形となります

main = do
 let x=[do
         a<-getLine 
         let b=read a::Int
         return b,
        do 
         a<-getLine 
         let b=read a::Int
         return b,
        do
         n<-x!!0 
         m<-x!!1 
         return $ n+m]::[IO Int]
 y<-do
     a<-x!!2
     return $ show a
 putStrLn y

doIO aを返す文脈なのでどこにでも書けて大変便利です
ランタイムに渡されない限り内部の手続きは一切評価されません
その反面処理を実行させたい場合はmainで明示的な評価式を用意する必要から若干冗長になります
IO Int同士は直接計算できないのでIntの取得には工夫が必要です

Discussion

ログインするとコメントできます