ふつうの haskell プログラミング (ふつける)

ふつうのHaskellプログラミング ふつうのプログラマのための関数型言語入門 読了.
問題の答えは最後にあるのね.

前ほどモナドが気にならなくなったので読んだ価値はあった.
あとは,wiki のソースを読んでみなきゃな.

問題やってみた↓

02-1.countbyte.hs

main:: IO ()
main = do cs <- getContents
          print $ length cs

02-2.countword.hs

main:: IO ()
main = do cs <- getContents
          print $ length $ words cs

03-1.swapa.hs

main:: IO ()
main = do cs <- getContents
          putStr $ swapa $ cs

swapa:: String -> String
swapa str = map translate str

translate:: Char -> Char
translate c | c == 'a' = 'A'
            | otherwise = c

04-1.sort.hs

import List

main:: IO ()
main = do cs <- getContents
          putStr $ unlines $ sort $ lines $ cs

04-2.uniq.hs

import List

main:: IO ()
main = do cs <- getContents
          putStr $ unlines $ uniq $ lines $ cs

uniq:: Eq a => [a] -> [a]
uniq cs = map head $ group cs

06-1.hs

resolve f (x:xs) = textify x ++ resolve f xs
resolve f (x:xs) = ((textify x) ++ ((resolve f xs))

getenv key env = fromMaybe "" $ lookup key env
getenv key env = (fromMaybe "" (lookup key env))

readTemplate id = readFile $ prefix repo ++ "/" ++ id
readTemplate id = (readFile (((prefix repo) ++ "/") ++ id)

07-1.fold.hs

main:: IO ()
main = do cs <- getContents
          putStr $ unlines $ fold $ lines $ cs

byteOfLine = 60

fold:: [String] -> [String]
fold ss = concat $ map fold' ss
    where fold' :: String -> [String]
          fold' []   = []
          fold' s    = let (x, y) = splitAt byteOfLine s
                       in x:(fold' y)

byteOfLine:: Int とは流石に書かないな.

08-1.strip.hs

import Char

main:: IO ()
main = do cs <- getContents
          putStr $ strip cs

-- 8.6.1
lstrip:: String -> String
lstrip = dropWhile isSpace

-- 8.6.2
rstrip:: String -> String
rstrip = reverse . lstrip . reverse

-- 8.6.3
strip:: String -> String
strip = rstrip . lstrip

./strip < 08-1.strip.hs など

08-4.tail.hs

-- 8.6.4
main :: IO ()
main = do cs <- getContents
          putStr $ lastNLines 10 cs

lastNLines :: Int -> String -> String
lastNLines n = unlines . (takeLast n) . lines

takeLast :: Int -> [a] -> [a]
takeLast n = reverse . (take n) . reverse

reverse . take n . reverse でも大丈夫なんだろうけど,なんだか気になるので括弧をつける.

08-5.fgrep.hs

-- 8.6.5
import System
import List

main :: IO ()
main = do args <- getArgs
          cs   <- getContents
          putStr $ fgrep (head args) cs

fgrep :: String -> String -> String
fgrep pattern = unlines . filter match . lines
    where match :: String -> Bool
          match = any prefixp . tails

          prefixp :: String -> Bool
          prefixp = isPrefixOf pattern

where 節でも型の宣言書けるのね.なるべく書こう.

09.line.hs

import List

-- 9.6.1
data Line = Line { number :: Int,
				   string :: String } deriving Show

-- 9.6.2
main :: IO ()
main = print $ Line 1 "One"

-- 9.6.4
takeN n = take n $ map (\a -> Line a $ show a) [1..]
{-
Main> takeN 5
[Line {number = 1, string = "1"},Line {number = 2, string = "2"},Line {number = 3, string = "3"},Line {number = 4, string = "4"},Line {number = 5, string = "5"}]
-}
-- 9.6.5
sortLines :: [Line] -> [Line]
sortLines = sortBy (\a b -> number a `compare` number b)
{-
Main> reverse $ takeN 5
[Line {number = 5, string = "5"},Line {number = 4, string = "4"},Line {number = 3, string = "3"},Line {number = 2, string = "2"},Line {number = 1, string = "1"}]
Main> sortLines $ reverse $ takeN 5
[Line {number = 1, string = "1"},Line {number = 2, string = "2"},Line {number = 3, string = "3"},Line {number = 4, string = "4"},Line {number = 5, string = "5"}]
-}

11-1.head.hs

import System
import List

-- 11.7.1
main :: IO ()
main = getContents >>= putStr . (firstNLines 10)

firstNLines :: Int -> String -> String
firstNLines n = unlines . (take n) . lines

11-2.tail.hs

-- 11.7.2
main :: IO ()
main = getContents >>= putStr . (lastNLines 10)

lastNLines :: Int -> String -> String
lastNLines n = unlines . (takeLast n) . lines


takeLast :: Int -> [a] -> [a]
takeLast n = reverse . (take n) . reverse

11-3.expand2.hs

tabStop = 8

main :: IO ()
main = getContents >>= putStr . expand

expand :: String -> String
expand cs = concatMap expandTab cs

expandTab :: Char -> String
expandTab '\t' = replicate tabStop ' '
expandTab c    = [c]

次は 入門Haskell―はじめて学ぶ関数型言語 を読んでみる.