en.wikibooks の Haskell に基づいたものです.CC-BY-SA での公開です.
h3> The need for a vocabulary
さてこうして関数の合成もできるようになり,あと再帰でもやれば色々書けるようになる,のだが,
その際には Haskell の standard libraries に何があるのかをある程度知っていることは,
コードの効率とか読みやすさ書きやすさ上結構重要になってきます.
standard libraries にある関数を自分で書き直すのももちろん勉強になるけどね.
というわけで,そのへんのこと,どう調べたらいいか,とかのお話.
Prelude and the hierarchical libraries
とうとう来ました.ghci を起動するときに出てくるアレ.Prelude>この
Prelude
はすべての Haskell プログラムでデフォルトで読み込まれる core library. これまで扱ったようなごく基本的な関数や,
map
とか filter
みたいなもうちょっと高級な(?)ものなど.そしてデフォルトでは読み込まれずに
import
(ghci からは :module
) する必要のある module たち,hierarchical libraries がある.
例えば
permutations
という関数が Data.List
にあって,これを使うときはソースで
import Data.List testPermitations = permutations "Prelude"ghci から読み込む場合は,前にも書いた通り
Prelude> :m Data.List複数読み込む(読み込まれる module を追加していく)時は
Prelude> :m +Data.Listと
+
を使う.折角だから使ってみましょう
Prelude> :m +Data.List Prelude Data.List> :t permutations permutations :: [a] -> [[a]] Prelude Data.List> permutations "sll" ["sll","lsl","lls","lls","lsl","sll"]つまるところこの
>
の左側にあるのは現在読み込まれてるライブラリ,という感じ.
One exhibit
便利なライブラリをちゃんと使おう,な話.関数:単語がスペースで区切られた文字列を受け取って単語を逆順に並べたのを返す.
the quick brown fox なら fox brown quick the になるもの. python なら
def rev_words(text): words = text.split() words.reverse() return " ".join(words)Haskell の
Prelude
にはこんな関数たちがいるのだ!
words
. (Tab とかもアリで)空白で区切られた単語を含む文字列を単語のリストにして返すreverse
. list を reverse するunwords
. words の反対.
revWords :: String -> String revWords input = (unwords. reverse. words) inputいい感じでかけます. 一方,上の便利な関数を使わず,これまでやってきたこと + ちょっと,だけ使うならこう書ける( '''ヤバ''' い).
monsterRevWords :: String -> String monsterRevWords input = rejoinUnreversed (divideReversed input) where divideReversed s = go1 [] s where go1 divided [] = divided go1 [] (c:cs) | testSpace c = go1 [] cs | otherwise = go1 [[]] (c:cs) go1 (w:ws) [c] | testSpace c = (w:ws) | otherwise = ((c:w):ws) go1 (w:ws) (c:c':cs) | testSpace c = if testSpace c' then go1 (w:ws) (c':cs) else go1 ([c']:w:ws) cs | otherwise = if testSpace c' then go1 ((c:w):ws) (c':cs) else go1 ((c:w):ws) (c':cs) testSpace c = c == ' ' rejoinUnreversed [] = [] rejoinUnreversed [w] = reverseList w rejoinUnreversed strings = go2 (' ' : reverseList newFirstWord) (otherWords) where revStrings = reverseList strings newFirstWord = head revStrings otherWords = tail revStrings go2 rejoined ([]:[]) = rejoined go2 rejoined ([]:(w':ws')) = go2 (rejoined) ((' ':w'):ws') go2 rejoined ((c:cs):ws) = go2 (c:rejoined) (cs:ws) reverseList [] = [] reverseList w = go3 [] w where go3 rev [] = rev go3 rev (c:cs) = go3 (c:rev) csもちろん初学者たる我々にとっては読めば勉強になるだろうけれど,基本的には読む気にならないし,アレ.
そもそもこれでほんとにちゃんと動くのか確信持てないしちょっと書き換えるのも大変そう.
さらにここで
testSpace c = c == ' 'とある通り,この場合単語を区切るのは半角スペースじゃないといけない (tab や 改行コードはだめ).
など,まあこれを使いたくはない.なお
Data.Char
にある isSpace
を使えばそのへん含めて空白か判定できる.らしい.と,まあ色々 ''ヤバ'' いので,しっかり使える道具は使いましょう,というおはなし.
Acquiring vocabulary
こういうのを知るにはどういう手だてがあるか.- the prelude specification
- GHC hierarchical libraries documentation
- Hoogle, ghc に入ってるライブラリを網羅した検索エンジン.
- Hayoo!, デフォルトでは入ってないのも含めていろんなライブラリをカバーする検索エンジン.
今日はここまで.
#企画開始時点での書き溜めがここで尽きたので,あす以降の更新はどうなるかわかりません.
No comments:
Post a Comment