『入門 自然言語処理』

オライリー・ジャパンのeStoreで『入門 自然言語処理』を購入。Haskellの勉強もまだまだ途中だというのに、大丈夫なんですかね。多分大丈夫じゃないです。
とりあえず「はじめに」は読み終わりました。pythonはすでにインストールしてありましたので、とりあえず対話シェルとたわむれています。

p7

以下を実行したら、matplotlibが必要と言われるなど。

>>> text4.dispersion_plot(["citizens", "democracy", "freedom", "duties", "America"])

http://www.matplotlib.orgからダウンロードしてインストール。
再び実行するとちゃんと表示してくれました。

すごいHaskell本

5章の続き、p70より。

下は、p72,chain関数の定義です。

chain :: Int -> [Int]
chain 1 = [1]
chain n
    | even n = n : chain (n `div` 2)
    | odd  n = n : chain (n * 3 + 1)

上のコードをghciに読ませると、non-exhaustiveと言われます。even n と odd n で全
てのパターンは網羅しているのだけれど、ghciはそこまで頭が良くないみたいですね。
otherwiseがないといけないみたい。警告が出るのは気持ち悪いですが、otherwiseを使
うと意図が分かりにくいコードになるので、このままにします。

-- otherwiseを使った場合
chain :: Int -> [Int]
chain 1 = [1]
chain n
    | even n    = n : chain (n `div` 2)
    | otherwise = n : chain (n * 3 + 1)  -- nが奇数のとき

ラムダ式。分かるような分からないような。「わかっていない感じ」が続く。きもちわるい。とりあえず進むのはよろしくないでしょうか。うーむ。

すごいHaskell本

今日も5章の続き。「5.2 高階実演」より。

5.2 高階実演

うーん? 部分適用は、すごいようなそうでないような。もうちょっと実践的な例がないとよくわからないです。
書いてあることはわかるのだけれど、でも「わかっていない感じ」がする。テトラちゃん。

p67の、「flipを実装する」。関数を簡潔化する手順が今ひとつ理解できないというか。
「わからない」とマークしておいて次に進みます。

5.3 関数プログラマの道具箱

map,filterとリスト内包表記

map関数やfilter関数と同じことをリスト内包表記でもできる、というおはなしでした。じゃあどっちを使えばいいのだろうと思った矢先に以下の文章。

どんなときにリスト内包表記ではなくmapとfilter関数を使うべきか、ルールのようなものは何もありません。コードと文脈に応じて、単純に読みやすいほうを採用してください。

よい本だと思います。



p70に、次のように書いてあります。

リスト内包表記で複数の述語を指定するようなケースをfilterで書くときには、filterを何度か適用するか、述語を論理関数&&でつないで指定します。

しかし、「述語を論理関数&&でつないで指定」するというのはどうすればよいのでしょうね。2つの関数を適用するような関数を自分で書いてfilterに渡せばいいってこと?
具体的には以下の様な感じするということです。

underFifteenEven :: Int -> Bool
underFifteenEven x = even x &&  x < 15

*Main> filter underFifteenEven [1..20]
[2,4,6,8,10,12,14]

もっとスマートな書き方があるのかしらん。

すごいHaskell本

今日も4章の続きです。「4.3 クイック、ソート!」から。

基底部と部分問題さえ正しく選んだなら、全体として何が起こるかの詳細を考える必要はありません。部分問題の解が正しいという保証を元に、より大きな最終問題の解を構築すれば良いだけです。

59ページより。

5章

高階関数に入ります。部分適用。
うーん、今ひとつピンとこない。書いてあることは分かる。完全には分かっていないの
だろうけれど。とりあえず進みます。

  • カリー化関数:常にちょうどひとつの引数をとる関数

メモ

Haskellで書いていて思うのは、「データをどこに格納して……」みたいな事を考えな
くていいということ。変数の状態が変わらないのだから当然なのだけれど。データは定
義するだけで操作しない、というか。正確な言い方ではないのでしょうが。

すごいHaskell本

今日から4章に入ります。4章は再帰
再帰については『Scheme手習い』を読んでたときに散々やったので、今のところは何も引っかかるところなくサクサク進みます。

1つだけ疑問点。引数の値を利用していないパターンで、アンダースコアではなく a などの変数を使っているところがあるのはなぜなのだろう。例えば56ページの elem' 関数とか。

elem' :: (Eq a) => a -> [a] -> Bool
elem' a [] = False
elem' a (x:xs)
    | a == x    = True
    | otherwise = a `elem'` xs

2行目で、2つ目の引数が空リストならば1つめの引数が何であろうと無条件でFalseを返しています。こういう場合にも、引数にaなどの文字を使っているのは、なにか慣習があるからのだろうか。

すごいHaskell本

今日は45ページから。「パターンマッチとwhere」

p45

initials :: String -> String -> String
initials firstname lastname = [f] ++ ". " ++ [l] ++ "."
    where (f:_) = firstname
          (l:_) = lastname

関数のパターンは網羅的なんだけど、whereでのパターンマッチでは空でないリストが
期待されているので、空文字列を渡すとExceptionが発生する。

*Main> initials "" ""
"*** Exception: chap3.hs:82:11-27: Irrefutable pattern failed for pattern (f : _)

引数でパターンマッチすると、ちゃんとコンパイル時に警告を出してくれる。(-Wall使用)

initials :: String -> String -> String
initials (f:_) (l:_) = [f] ++ ". " ++ [l] ++ "."
chap3.hs:81:1:
    Warning: Pattern match(es) are non-exhaustive
             In an equation for `initials':
                 Patterns not matched:
                     [] _
                     (_ : _) []

昨日の、constraintsが云々の警告の話。
第2回 スタートHaskell 感想 - 酔いどれコードを参考にし
て、-fno-warn-type-defaults オプションをつけたらとりあえず消えた。

あと、~/.ghci に

:set -O
:set -Wall
:set -fno-warn-type-defaults

というように書くと毎回オプションを付けてくれるそうな。Windows7でも、ホームディレク
トリに同じものを置いたら、ちゃんと読み込んでくれました。

……ここまでで1時間経過。色々調べてると1時間で1ページも進まないですねー。ま
あ、じっくりいきましょう。

メモ

  • whereのスコープはひとつのパターン内
  • whereはキーワード
  • letは式→値を持つ
  • letはローカルスコープに関数を作るのに使える
  • letはセミコロン区切りを使える

うーん、let式とcase式のところも終わったけれど、今ひとつピンとこない。とりあえ
ず今は進もう。後になって戻ってくれば分かるようになっているかもしれないから。
次は第4章、再帰について見ていきますよ。

すごいHaskell本

第3章を進めております。

関数を定義する際、引数の構造で場合分けするときにはパターンを使います。
引数の値が満たす性質で場合分けするときには、ガードを使います。

ふつうのHaskell本を読んでたときは、パターンマッチとガードの違いがよく分からな
かったので、上の解説は助かります。

p42の bmiTell を -Wall -Werror オプション付きで実行するとエラーが出るんですが、こ
れは何なのでしょうね。

bmiTell :: Double -> Double -> String
bmiTell weight height
  | weight / height ^ 2 <= 18.5 = "You're underweight, you emo, you!"
  | weight / height ^ 2 <= 25.0 = "You're supposedly normal.\
                    \ Pffft, I bet you're ugly!"
  | weight / height ^ 2 <= 30.0 = "You're fat! Lose some weight, fatty!"
  | otherwise   = "You're a whale, congratulations!"
chap3.hs:49:21:
    Warning: Defaulting the following constraint(s) to type `Integer'
               (Integral b0) arising from a use of `^' at chap3.hs:49:21
               (Num b0) arising from the literal `2' at chap3.hs:49:23
    In the second argument of `(/)', namely `height ^ 2'
    In the first argument of `(<=)', namely `weight / height ^ 2'
    In the expression: weight / height ^ 2 <= 18.5

chap3.hs:50:21:
    Warning: Defaulting the following constraint(s) to type `Integer'
               (Integral b0) arising from a use of `^' at chap3.hs:50:21
               (Num b0) arising from the literal `2' at chap3.hs:50:23
    In the second argument of `(/)', namely `height ^ 2'
    In the first argument of `(<=)', namely `weight / height ^ 2'
    In the expression: weight / height ^ 2 <= 25.0

chap3.hs:52:21:
    Warning: Defaulting the following constraint(s) to type `Integer'
               (Integral b0) arising from a use of `^' at chap3.hs:52:21
               (Num b0) arising from the literal `2' at chap3.hs:52:23
    In the second argument of `(/)', namely `height ^ 2'
    In the first argument of `(<=)', namely `weight / height ^ 2'
    In the expression: weight / height ^ 2 <= 30.0