9ad2c3de.jpg

ながかったスタートHaskellも今回で最終回。ちょっと仕事がいそがしくなってて今回はほとんど問題を解いてない。いつものように神保町のマクドナルドでいつものハンバーガーで腹ごしらえして会場へ。空腹対策にプロテインとインスタントコーヒーとブドウ糖の混合液をもっていった。甘いだけのものより腹持ちがよかったような気がした。

16fc1894.jpg

12章: Lazy Evaluation @imsuten

  • http://www.intransient.info/materials/Programming_in_Haskell_12/Programming_in_Haskell_12.html5.html
  • const 1 (div 1 0)は?: エラーと停止しないはHaskellでは同じ。かんがえなくてよい。
  • 評価順をどうするか→評価戦略
  • 関数を適用することで式を簡約できるものを: reducible expression(簡約可能な式)、redex(簡約項) という。
  • (Leftmost) Innermost evaluation: 関数適用より先に引数が評価される。
  • (Leftmost) Outermost evaluation: 外側から内側、左から右の順に簡約する。+や*は正格(strict)関数なので先に評価される。
  • Lambda内は簡約しない。
    • (\x -> 1 + 2) 0
    • = (\x -> 3) 0
    • = 3
    • ということはHaskellではなされない。lambdaはブラックボックス。
    • ラムダ抽象をしっている人からするとlambdaの中を簡約するのはおかしいとおもう。関数に引数を与えないと発火しないので引数を与える前にいじるのはおかしい。
    • 部分計算というのとちかい。
    • コンパイル時の最適化の話とはちがう。
    • 最外簡約で本当に必要なところしか計算しないということからするとlambdaの中を評価するのはあわない。
  • ghcは共通部分式の削除をあまりやらないのでletをつかったほうがいいらしい。
    • square (1 + 2) で 1+2を二回評価してしまうおそれはない。同じ式だとわかっているのでメモ化される。
    • (1+2)*(1+2)という式では共通部分式を削除するのはコンパイラの最適化。
    • call-by-need: 名前がついていれば同じ式を一度しか評価しない。
    • call-by-name+式の共有=call-by-need=lazy-evaluation
  • ones = 1:ones はconscellは1個だけ。take 5 onesはコピーが発生して5個のcellができる。
    • 日比野さんに詳しく話をきいてみた感じだとCでいうとこんなかんじっぽい:
    struct x {
	int elem;
	struct x* next;
    } ones = { 1, &ones };
    struct y {
	int elem;
	struct y& next;
    } twos = { 2, twos };
    /*こうではない
    struct z {
	int elem;
	struct z next;
    } threes = { 3, threes };
    */
  • - あと repeat x = xs where xs = x:xs と定義されているが、repeat x = x : repeat x で試してみるとrepeat xが何度も呼ばれてconsがいっぱいできてしまうようだ。
cons x xs | trace("cons") False = x:xs
cons x xs = x:xs
repeat1 x = xs where xs = cons x xs
repeat2 x = cons x (repeat2 x)

*Main> take 3 (repeat1 1)
cons
[1,1,1]
*Main> take 3 (repeat2 1)
cons
[1cons
,1cons
,1]
*Main>
  • $!はパターンではない。ダラーバン二項演算子。
    • f $! x = seq x (f x)
  • WHNF
    • weak head normal formの略
    • weak: lambda内は簡約しない
    • head: top levelが関数やデータコンストラクタになったらそれ以上簡約しない。
    • normal form: という正規形
    • RNF: 0 とか "Hello"
    • HNF: (\x y -> x + y) (1+2)
    • WHNF: \x->((\y->x+y) 3) とか (1+2):3: これに$!をつけてもx+3とか3:3:にならない
inc x | trace("inc " ++ show x) False = x + 1
inc x = x + 1
*Main> take 0 $! [(inc 1), 2]
[]
*Main> const 1 (inc 1)
1
*Main> const 1 $! (inc 1)
inc 1
1
*Main>
  • - WHNFですらない; 1+2 とか (\x -> x * 2) 3。 これが$!で簡約されてWHNFになる。
  • リストの中身までを簡約したいときがある。ベンチマークとか。deepseqというのをつかうと全部簡約される。
  • よくわからなかったメモ:
    • ⊥ `seq` b = ⊥, if a = ⊥
    • a `seq` b = b, if a /= ⊥

[2012-01-28 14:03]

12章 演習問題発表

  • (1+2)*(2+3) 最内は1+2と2+3 (評価順序は左からだが両方が最内)
  • (1+2)*(2+3)*(3+4)なら((1+2)*(2+3))*(3+4)で右の*が最外
  • あまり議論しても得られるものはないby kazu
  • fibs@(_:tfibs) = 0 : 1 : zipWith (+) fibs tfibs

[2012-01-28 14:31]

休憩

[2012-01-28 14:51]

13章 Reasoning about Programs @imsuten

reverse (x1:x2:xs)
 = reverse (x2:xs) ++ [x1]
 = (reverse xs ++ [x2]) ++ [x1]
 = reverse xs ++ ([x2] ++ [x1])
 = reverse xs ++ (x2:[x1])
  • 末尾再帰最適化だけじゃないことをいいたんだろうが。
  • ++に対する:があるときに効率化されるが。

[2012-01-28 15:41]

[2012-01-28 15:45]

13章 演習問題

[2012-01-28 16:50]

[2012-01-28 17:05]

LT

QuickCheck @Lost_dog_

  • http://itpro.nikkeibp.co.jp/article/COLUMN/20080304/295346/
  • 性質を書いたらランダムチェックできる。
  • prop_xxx a b = expr a b == expr' a b
  • instance arbitrary Nat where ... でテストデータの生成方法を指定する必要がある(かもしれない)。
  • タイムアウトも指定できる。

shpider @dekosuke

@shtaag

@yunomu11

  • erlangに浮気とかしてたけどやっぱり気になる。
  • あたらしいプログラミング言語を学ぶときは電卓をつくってる。
  • 構文解析がめんどうなので逆ポーランドのdcをつくってみた。
  • スタック(状態)をもつのでMonadのつかいかたがわかった。

本当は恐いReal World Haskell @VoQn

  • http://voqn.blogspot.com/2011/12/haskell.html
  • 浮動小数点の誤差とかtry catchできないとか。
  • map (/ 10^^n)[i,(i+k)..] とすると誤差のない数列がえられる。
  • x / 10^^n の方がいい。x * 10^^(-n) だと誤差がでる。
  • [0,0.1..1.0] と書けるが、どうやって生成しているのかはコードを読んでみないとわからない。
  • せいかくすう/ひせいかくすう?
  • rubyだと[0.0,0.1..1.0]相当のはきれいな数にまるめるらしい。
Prelude> [0,0.1..1.0]
[0.0,0.1,0.2,0.30000000000000004,0.4000000000000001,0.5000000000000001,0.6000000000000001,0.7000000000000001,0.8,0.9,1.0]
Prelude> 0.0+0.1
0.1
Prelude> 0.0+0.1+01
1.1
Prelude> 0.0+0.1+0.1+0.1
0.30000000000000004
Prelude> 0.0+0.1+0.1+0.1+0.1
0.4
Prelude> 0.0+0.1+0.1+0.1+0.1+0.1
0.5
Prelude> 0.0+0.1+0.1+0.1+0.1+0.1+0.1
0.6
Prelude> 0.0+0.1+0.1+0.1+0.1+0.1+0.1+0.1
0.7
Prelude> 0.0+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1
0.7999999999999999
Prelude> 0.0+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1
0.8999999999999999
Prelude> 0.0+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1
0.9999999999999999
Prelude> 0.0+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1
1.0999999999999999
Prelude>

Hoogle @虎

@khibino

  • http://d.hatena.ne.jp/khibino0/20111212/1323680441
  • ブログ advent calendar
  • ghciのデバッガ機能
  • break step print backstep traceなど
  • forceで強制評価
  • 例外がどこからとんできたか調べるのにはよくつかう。
  • printfデバッグをつかうけどデバッガでできるのはやっぱり便利。
  • サンクはみえない。たぶん実行時最適化されているのでむり。

@kazu_yamamoto

  • http://d.hatena.ne.jp/kazu-yamamoto/20120112/1326335764
  • BDD: behavior driven test
  • TDDとちかいが、テストをばりばり書くという感じではない。テストを書いていると仕様がかたまるという感じ。
  • 関数の型を先に書くのは初歩のBDDになる。
  • haddock: コメントに実行例が書ける。
  • 副作用があるときはunit testをつかわないといけない。(quickcheckは純粋なものに限られる)

[2012-01-28 18:29]

勉強会の紹介 @master_q

[2012-01-28 18:36]

アンケート結果

[2012-01-28 18:40]