Arantium Maestum

プログラミング、囲碁、読書の話題

Thinking Functionally with Haskell勉強メモ: 第1章

第1章は「関数型言語とは?」という問いへの著者なりの答えから始まる。

Richard Birdの「関数型プログラミング」定義は:

  • 関数とその適用を重視するプログラミング(命令とその実行ではなくて)
  • 簡明な数学的記法で問題を記述することができる
  • 数学的な裏付けがあり、等価性の法則を使ってプログラムの性質を考えることができる

とのこと。プログラマは皆胸の中に「マイ関数型プログラミング定義」を持っている。

そこからいきなり関数と型(関数の型?)の話になるのがHaskellらしい。概ねサプライズなしだが、f 2*a(f 2) * a)になるのは初めの方はうっかりしそう。

「文字列から頻度の高い単語のリストを作成」という例題で、「この関数が存在すると仮定して使っていこう」と書いてあるのはSICPを彷彿とさせた。実際どんな言語でも大き目の問題を解く場合はそういう順番で考えるけど、入門書の最初の例題でその飛躍をいとも簡単にするのって珍しいよね。

最終的にこの例題が

commonWords :: Int -> [Char]-> [Char]
commonWords n = concat . map showRun . take n . sortRuns . countRuns . sortWords . words . map toLower

と処理の流れを綺麗に表す形になるのはいいな。Clojureのthreadingマクロに慣れているので、処理の順番が逆に記述されていた方がちょっとわかりやすい気はしてしまうが・・・

あと目に留まったのはguarded equation + where clause:

convert :: Int -> String
convert n
  | m==x       = a
  | m==y       = b
  | m==z       = c
  | otherwise = d
  where m = f n

この記法になれるのにちょっと時間がかかるかな?と思った。

最後はglasgow haskell compiler interpreterのREPL環境についての説明。ターミナルでghciと叩いて起動。

気になったのは、関数は別ファイルに定義してインタプリタで読み込むという形で紹介していること。REPLで直接関数を定義したいと思って型定義を入力してみたのだがエラーが出てしまう。調べたところ:{:}に囲むことで一行ごとに評価されなくなるので

ghci> :{
ghci|  myFunc :: Int -> Int
ghci|  myFunc n = 2*n
ghci| :}

といった形でREPLで直接関数が定義できる。これを使って次は章末の問題を解いていきたい。