ファイルとストリーム
ファイルの内容を読み込んで大文字にして返すプログラム
haiku.txt
I'm a cat nyaaan nyaaan nyaaaan nyaaan nyaaaan nyaaaaaaaaaan
実装
import Control.Monad import Data.Char main = forever $ do l <- getLine putStrLn $ map toUpper l
ビルド
> stack ghc -- --make capslocker.hs [1 of 1] Compiling Main ( capslocker.hs, capslocker.o ) Linking capslocker ...
実行する
> ./capslocker < haiku.txt I'M A CAT NYAAAN NYAAAN NYAAAAN NYAAAN NYAAAAN NYAAAAAAAAAAN capslocker: <stdin>: hGetLine: end of file
ストリームから文字列を得るプログラム
import Data.Char main = do contents <- getContents putStr $ map toUpper contents
実行
> ./capslocker < haiku.txt I'M A CAT NYAAAN NYAAAN NYAAAAN NYAAAN NYAAAAN NYAAAAAAAAAAN
端末から入力を読み込む
> ./capslocker hoge HOGE foo fuga FOO FUGA
getContents
は遅延I/Oなので必要な時に入力から行を読み込む。
getContents
の結果が contents に束縛される時、
文字列としてではなく、最終的に文字列に評価されるプロミス(promise)として
メモリ上に置かれる。
contents に toUpper をマップする時もまだプロミスのままで、 putStr が呼ばれるとEOFが入力されるまで入力をとってくる。
入力を受け取り、10文字より短い行だけを出力するプログラムを作る
main = do contents <- getContents putStr (shortLinesOnly contents) shortLinesOnly :: String -> String shortLinesOnly = unlines . filter (\line -> length line < 10) . lines
lines はこんな動き
*Main Lib> lines "aaaaa\nbbbbb\nccccc" ["aaaaa","bbbbb","ccccc"]
filter で10文字未満の長さの要素だけ返す
unlines はこんな動き
*Main Lib> unlines ["aaaaa","bbbbb","ccccc"] "aaaaa\nbbbbb\nccccc\n"
入力するファイル
i'm short so am i i am a looooooooooooooooooooooooong line!!!! yeah i'm long so what hahahahahaha!!!! short line loooooooooooooooooooooooong short
ビルドして実行する
> stack ghc -- --make shortlinesonly.hs [1 of 1] Compiling Main ( shortlinesonly.hs, shortlinesonly.o ) Linking shortlinesonly ... > ./shortlinesonly < shortlines.txt i'm short so am i short
入力を変換する
入力を文字列として受け取り、関数で変換、結果を出力する。という 操作は頻出するので、interact という便利な関数が用意されている
先程のプログラムを interact を用いて書き換える
main = interact shortLinesOnly shortLinesOnly :: String -> String shortLinesOnly = unlines . filter (\line -> length line < 10) . lines
interact は String -> String 型の関数を受け取り、 入力にその関数を適用して、返ってきた結果を出力する。
入力を行毎に読み込んで、回文かどうか出力するプログラムを書く
respondPalindromes :: String -> String respondPalindromes = unlines . map (\xs -> if isPal xs then "palindrome" else "not a palindrome") . lines isPal :: String -> Bool isPal xs = xs == reverse xs main = interact respondPalindromes
ビルド・実行
> stack ghc -- --make palindrome.hs [1 of 1] Compiling Main ( palindrome.hs, palindrome.o ) Linking palindrome ... > ./palindrome hehe not a palindrome ABCBA palindrome 11223344332211 palindrome
所感
入力 -> 変換 -> 出力 の流れを体験できるようになった。
遅延I/Oのイメージは関数の遅延評価と同じでなんとなく把握できたが、 遅延I/Oだとなにが嬉しいのかがいまいちわからん。

- 作者: MiranLipovaca
- 出版社/メーカー: オーム社
- 発売日: 2017/07/14
- メディア: Kindle版
- 購入: 4人 クリック: 9回
- この商品を含むブログを見る