Haskell その1
Haskellでdiffを書けないものかと悪戦苦闘。
『やさしいHaskell入門』を読む。
http://www.sampou.org/haskell/tutorial-j/index.html
どこがやさしいのだ?w
こういうときはとにかく書いてみる。
まずはcatを書いてみる。
import System cat :: String -> IO String cat fn = do cs <- readFile(fn) return cs cats :: [String] -> IO String cats (x:xs) = do cs1 <- cat x cs2 <- cats xs return (cs1 ++ "\n" ++ cs2) main = do args <- getArgs cs <- cats args putStr cs
ほんとはもっと試行錯誤したけど、コンパイル。
$ /cygdrive/c/ghc/ghc-6.4.1/bin/ghc cat.hs
コンパイルは出来た。
しかし、あやすぃ。とくに再帰させてるつもりのcatsが。
でも動かす。
$ ./main.exe cat.hs main.exe: cat.hs:(9,0)-(12,28): Non-exhaustive patterns in function cats
だよなぁ、リストが空のとき:: [String] -> IO Stringという定義の関数は
どういう値を返せばいいのかわかんない…。
っていうか、関数じゃない?アクションですか。
じゃあ、空のアクションということで…
import System cat :: String -> IO () cat fn = do cs <- readFile(fn) putStr cs cats :: [String] -> IO () cats [] = return () cats (x:xs) = do cat x cats xs main = do args <- getArgs cats args
おお、動くよ、動く。
でも…なんだかなぁ、全然関数型プログラミングっぽくない。
doが非常に邪道な気がしてならない(関数型のなんたるかを知りもせずw)。
じゃ、そろそろ他の人のcat実装例を見てみる。
import System main = do args <- getArgs case args of [] -> putStr =<< getContents _ -> mapM_ (\a -> putStr =<< readFile a)
map?ああ、mapね、map。そりゃいい。
\?ああ、lambdaじゃん、こんにちは。
さらに、
import System main = getArgs >>= mapM readFile >>= mapM_ putStr
エレガントだ。笑うしかない。
くやしいので自分のコードの改良を進める。
>>=ってなんだ?え?もうモナドの森へ迷いこまなきゃいけないのか。
モナドの謎は最後にとっておこうと思ったのにぃ。
import System cat fn = readFile(fn) >>= putStr cats [] = return () cats (x:xs) = cat x >> cats xs main = getArgs >>= cats
はぁ、多少すっきり?
そりゃね、mapとlambdaのほうが適してるのは分かる。
でもね、(x:xs)で再帰してみたかっただけで…
むしゃくしゃしてやった。今は反省している。