すごいHaskell六章(前半)
文法三昧から少しソフトウェアっぽくなってくる
import
モジュールのインポート。qualifiedで名前空間を分けられる。qualified as で別名を付けて短縮できる。
単語数えたりするところ
ちょっとwordsやgroupの挙動が気になったので。
wordsはスペースでsplitする感じなのかな。(Haskellにsplitがあるかどうかは知らないけど)
ghci> words "hey these ar e the words in this sentence" ["hey","these","ar","e","the","words","in","this","sentence"]
group、結構いろんな挙動する。
ghci> group ["boom", "boom", "bip", "bip", "boom"] [["boom","boom"],["bip","bip"],["boom"]] ghci> group ["boom", "bip", "bip", "boom"] [["boom"],["bip","bip"],["boom"]]
あ、ちょっと誤解してたかもしれない。これは同じ要素をリストにまとめる関数なのか。じゃ、連続している"boom"や"bip"が1つのリストに入るのは正しい挙動だ。で、sortと組み合わせると要素をまとめられると。
これ実行できない理由がわからない。
ghci> group . sort ["boom", "bip", "bip", "boom"] <interactive>:17:9: Couldn't match expected type `a0 -> [a1]' with actual type `[a2]' In the return type of a call of `sort' Probable cause: `sort' is applied to too many arguments In the second argument of `(.)', namely `sort ["boom", "bip", "bip", "boom"]' In the expression: group . sort ["boom", "bip", "bip", "boom"]
括弧だと出来る。
ghci> group(sort ["boom", "bip", "bip", "boom"]) [["bip","bip"],["boom","boom"]]
関数合成は定義でしかできないってこともないだろうに。
と思ったら、こう書くらしい。
ghci> (group . sort) ["boom", "bip", "bip", "boom"] [["bip","bip"],["boom","boom"]]
関数合成は右結合だから、group . (sort ["boom", "bip", "bip", "boom"])ってなっちゃたのかな。( . 演算子の型が合わなくなる)
関数定義の時は、カリー化で引数は後で受け取ることになるから括弧が必要ないのか。
wordNums
スペースで区切られた文字列を受け取って、それぞれの単語の数を返す。
import Data.List wordNums :: String -> [(String, Int)] wordNums = map (\ws -> (head ws, length ws)) . group . sort . words
groupするとリストのリストになるっていうの、すぐ忘れる。リストのリストだからheadすると先頭リストが取り出せるし、lengthで先頭リストの長さが得られるのか。
ところで、関数定義の中で、(\ws -> (head ws, length ws))の部分、なんでheadして取り出した文字列に対してlengthが実行されるのかわからない。headとlengthを別々にwsに適用すると、当然groupされてできたリストのリスト全体の長さが返ってくる。
ghci> head $ (group . sort . words) "wa wa wee wa" ["wa","wa","wa"] ghci> length $ (group . sort . words) "wa wa wee wa" 2
あ、mapだからか……それぞれの要素に対して適用されるのね…
ghci> map head $ (group . sort . words) "wa wa wee wa" ["wa","wee"] ghci> map length $ (group . sort . words) "wa wa wee wa" [3,1]
当たり前の話だった。