RWH p.92 練習問題 3

import System.Environment (getArgs)

interactWith function inputFile outputFile = do
    input <- readFile inputFile
    writeFile outputFile (function input)

main = mainWith myFunction
    where mainWith function = do
            args <- getArgs
            case args of
                [input, output] -> interactWith function input output
                _ -> putStrLn "error: exactly two arguments needed"
          myFunction = firstWord

firstWord :: String -> String
firstWord = unlines . map (fromMaybe "") . map safeHead . map words . splitLines

splitLines :: String -> [String]
splitLines [] = []
splitLines cs =
    let (pre, suf) = break isLineTerminator cs
    in pre : case suf of
               ('\r':'\n':rest) -> splitLines rest
               ('\r':rest)      -> splitLines rest
               ('\n':rest)      -> splitLines rest
               _                -> []

isLineTerminator c = c == '\r' || c == '\n'

safeHead :: [a] -> Maybe a
safeHead [] = Nothing
safeHead (x:_) = Just x

fromMaybe :: a -> Maybe a -> a
fromMaybe def val =
    case val of
        Nothing -> def
        Just v -> v

ここまでに出てきたものいろいろ組み合わせてみた。splitLinesで行ごとにして、それぞれの行に対してwordssafeHeadで最初の要素を抜き出して、fromMaybeでMaybeを外す。unlinesでくっつけて出来上がり。