Real World Haskell 4.5 練習問題
久しぶりに Haskell。Real World Haskell の本を買ったはいいがなかなか進まない。まだ 4章。
問1
Maybe型で返すのはいいけど、返されたMaybe型の値をどう扱えばいいかまだわかっていない。
safeHead xs = if null xs then Nothing else Just (head xs) safeTail xs = if null xs then Nothing else Just (tail xs) safeLast xs = if null xs then Nothing else Just (last xs) safeInit xs = if null xs then Nothing else Just (init xs)
問2
ネストが深い?
splitWith f xs = let (pre, suf) = break f xs in if null pre then splitWith f (tail suf) else pre : if null suf then [] else splitWith f (tail suf)
2010/07/29 修正
splitWith f xs = let (pre, suf) = span f xs in if null pre then tailSplitWith f suf else pre : tailSplitWith f suf where tailSplitWith f (x:xs) = splitWith f xs tailSplitWith f [] = []
問3
ファイルの入出力部分は省略。次の問4も同様。map を使えばもう少し単純に書けるはず。でも、ここまででの内容で map はなかったような。なので、あえて使わずに解いてみた。
myFunction = initials initials :: String -> String initials input = unlines (headStrs (lines input)) where headStrs (x:xs) = headStr x : headStrs xs headStrs _ = [] headStr (x:xs) = [x] headStr _ = []
問4
問 1 で作った safeHead, safeTail を使おうと思ったが、前述の通り Maybe 型の扱い方がわからないので myHead, myTail を作った。
リストが空かの判定をパターンマッチを使っている関数と if 式を使っている関数がある。まとめた方がよかったかな。
myFunction = rotateLines myHead :: String -> Char myHead xs = if null xs then ' ' else head xs myTail :: String -> String myTail xs = if null xs then [] else tail xs heads :: [String] -> String heads (x:xs) = myHead x : heads xs heads _ = [] tails :: [String] -> [String] tails (x:xs) = myTail x : tails xs tails _ = [] rotate :: [String] -> [String] rotate xs = if null (concat xs) -- これが終了判定 then [] else heads xs : rotate (tails xs) rotateLines :: String -> String rotateLines xs = unlines (rotate (lines xs))
関数が多くなってくると次に作る関数名をどうしようか悩む。もう少しボキャブラリーが多ければな〜。