2015-12-22 『ふつうのHaskellプログラミング』 もくもく読書会(第4章) の振り返り
ふつうのHaskellプログラミング ふつうのプログラマのための関数型言語入門
- 作者: 青木峰郎,山下伸夫
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2006/06/01
- メディア: 単行本
- 購入: 25人 クリック: 314回
- この商品を含むブログ (320件) を見る
第4章 Haskellの基礎(3) モジュールと総合演習
注意事項
この本が書かれた後にHaskellが新しくなりimportするモジュールが変わっているのでimportする際に注意
- System → System.Environment
- List → Data.List
echo.hs
- コマンドライン引数を標準出力するコマンド
モジュール
- Haskellプログラムはモジュールという単位で分割されている
- 関数や変数や型の集まり
- javaでいうパッケージのようなもの
- 他のモジュールで定義されている関数を使いたい場合はimport宣言が必要
getArgs
ともSystem.Environment.getArgs
とも書ける
Mainモジュール
- main変数が属するモジュール
- モジュールの宣言を何も書かないとファイル全体がMainモジュールとなる
Preludeモジュール
- 基本的な型や関数が定義されたモジュール
- すべてのモジュールは暗黙のうちにPreludeモジュールをインポートしている
unwords関数
unwords :: [String] -> String
- 文字列のリストの各要素を空白を入れて連結する関数
- 例:
["abc", "de", "fg"]
→"abc de fg"
getArgs関数
getArgs :: IO[String]
- System.Environmentの関数
- プログラムのコマンドライン引数を読み込むアクション
コメント
この本だとunwords関数
とgetArgsアクション
とあり、「関数」と「アクション」に定義の違いがあるのか気になる。
ちなみに「getArgs関数」と書いてある箇所もある。
→ アクションについてはp26に、11章で改めて説明するとある
頂いたコメントのように下記の点を押さえておけば現状はOK。
p26の説明通り、評価するとなぜかIOなどの副作用ができる。 つまり、「引数と返り値のみの関数とは違うものですよ。」ということだけ押さえて
fgrep.hs
- 特定の文字列を含む行だけ抜き出すコマンド
- コマンドライン引数と標準入力を受け取る
> fgrep ar < USA-states.txt DE Delware MD Maryland …略
このようにUSA-states.txt内で「ar」を含む行が出力される
- Delw"ar"e
- M"ar"yland
head関数
- リストの最初の要素を返す関数
- 空リストの場合はエラー
head :: [a] -> a
tail関数
- リストの最初の要素を除いたリストを返す
- 空リストだとエラー
filter関数
- 引数に渡したリストの要素が同じく引数の関数でtrueを返すもののみで構成されたリストを返す
filter :: (a -> Bool) -> [a] -> [a]
例:リストを奇数のみにする
> filter (\x -> x mod 2 == 1) [1,2,3,4,5] [1, 3, 5]
fgrepの定義
fgrep :: String -> String -> String fgrep pattern cs = unlines $ filter match $ lines cs where match :: String -> Bool match line = any prefixp $ tails line prefixp :: String -> Bool prefixp line = pattern `isPrefixOf` line
- fgrep関数の第1引数
pattern
はコマンドラインで指定した文字列 fgrep関数の第2引数
cs
は標準入力で読み込んだ文字列lines cs
→ csの複数行の文字列を行ごとのリストにするfilter match $ lines cs
→ リストの各行をmatch関数に渡して結果がTrueのもののみのリストにする- match関数内の
tails line
→ 受け取った行の文字列をtails関数を使って下記のような文字列のリストをつくる
> tails "abcde" ["abcde", "bcde", "cde", "de", "e", ""]
any prefixp $ tails line
→ tails関数の要素をprefixp関数に渡して評価し、Trueになればany関数がTrueを返す- prefixp関数内の
pattern `isPrefixOf` line
→ patternの文字列がlineの開始文字列と一致すればTrue unlines $ filter …略
→ unlines関数でfilterの結果のリストをひとつの文字列にする
pattern `isPrefixOf` line
は下記と同じ
isPrefixOf pattern line
where節
- その式だけに有効な定義を導入するための構文
- 定義毎に改行が必要
- 式とwhere句およびwhere句と定義1は改行があってもなくてもよい
式 where 定義1 定義2 定義3 …略
tails関数
- Data.Listモジュールの関数
tails :: [a] -> [[a]]
例:
> tails "abcde" ["abcde", "bcde", "cde", "de", "e", ""]
any関数
- リストの要素を検証して、どれか一つでもTrueを返せばTrueを返す。
- 全てがFalseならFalseを返す
any :: (a -> Bool) -> [a] -> Bool
isPrefixOf関数
- Data.Listモジュールの関数
- 指定したリスト(pattern)が調査対処のリスト(line)
isPrefixOf :: (Eq a) => [a] -> [a] -> Bool
練習問題
問1と問2
- 解答の内容には特に問題なし
- いきなり
lines =<< getContents
が出てくるけど、どこかで説明が出ていた?