静岡Developers勉強会 第11回 第12章 遅延評価

860 views

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
860
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
2
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

静岡Developers勉強会 第11回 第12章 遅延評価

  1. 1. 静岡Developers勉強会 第11回Programming Haskell読書会 第12章 遅延評価 tw:ishisaka
  2. 2. 遅延評価  必要となるまで関数の引数を評価しないこと
  3. 3. 手続型言語と純粋関数型言語  手続型(命令型)言語では式の評価順序が変わると計算 結果が変わってしまう。  Haskellでは状態を持たないので式の評価順序が変わっ ても結果は変化しない。  それでも評価の順番は実用上の重大な問題
  4. 4. 評価戦略  一つ以上の引数へ適用されている関数を含み、その適 用を実行すると簡約可能な式は、簡約可能式(redex)と 呼ばれる。  式を簡約すると通常は大きさ小さくなるが、いつでも小さ くなるとは限らない。
  5. 5. multi :: (Int, Int) -> Int multi(x, y) = x * y multi (1 + 2, 2 + 3) を簡約すると? multi (3, 2+3), multi (1 + 2, 5), (1 + 2) * (2 + 3)に簡約される
  6. 6. 評価戦略(最内簡約)  簡単にまとめると引数を先に評価していく  手続型に慣れていると自然な流れ  式の内側から、それ以上内側がなければ左から簡約していく muti (1 + 2, 2 + 3) [ 1+2と2+3はこれ以上簡約できない] = multi (3, 2 + 3) = multi (3, 5) = 3 * 5 = 15  このように最内の式を評価して関数に引数を渡すことを「値渡 し」と呼ぶ
  7. 7. 評価戦略(最外簡約)  外側の関数から簡約する  Haskellの評価方法はこちら multi(1 +2, 2 + 3) = (1+2) * (2+3) [関数が適用される] = 3 * (2+3) = 3 * 5 = 15  この場合は引数は(まだ評価されていないので)「名前」として 渡されていると表現する(名前渡し)
  8. 8. 評価戦略(正格)  Haskellの組み込み関数や*,+のような演算子は引数二 つが評価されて数値にならないと適応できない。  このような性質を持つ関数は「正格」であると呼ばれる。
  9. 9. λ式  Haskellではλ式の中の簡約可能式を選択ことは禁止  λ式の中はブラックボックスで触っちゃダメ  許されるλ式への操作は、引数の適用だけ  適用して,中身を取り出してはじめて中の簡約式に触れ る  λx->1+2  1+2は簡約可能であるが、完全に評価済みとみなす
  10. 10. 停止性 inf = 1 + inf この式はずーーーっと再帰を繰り返すので終わらない。 fst(0, inf)  fstは組の最初の要素を返す関数  通常の手続型言語だと最内簡約なので先にinfの評価を始 めるので永久に式は終わらない  Haskellは名前渡しなので、最初にfst関数が適応され、最初 の要素である0が返される。  つまり結果としてinfの評価はしないので、式が永久に終わ らないという事はない。  遅延評価なら理論的に終了できるなら終了できる
  11. 11. 遅延評価  名前渡しでは引数がコピーされてから評価されることが あるので、同じ引数が何度も評価されうる。 名前渡しの例: square (1 + 2) = (1+2) * (1+2) = 3 * (1+2) = 3 * 3 =9  引数が複数回評価され、値渡しより名前渡しのほうが簡約の 回数が増える場合がある。
  12. 12. 遅延評価  名前渡しの効率の悪さは共有される式をポインタで刺す という方法で解決できる  square(1+2)という式であれば、1+2の結果はポインタで共有で きる。したがって実際にはこの場合式の簡約を1回減らすこと ができる。  グラフ簡約  ポインタによる共有を用いた名前渡しは「遅延評価」と呼 ばれる  Haskellのとる評価戦略はこの遅延評価である。
  13. 13. 無限のデータ構造  遅延評価のおかげで無限の構造を持つデータが扱える  onesのような無限リストは潜在的無限リストであって、遅 延評価であればコンテキストが必要とされる部分だけが 評価される。 head ones = head (1:ones) = 1 <遅延評価であればここで処理が終わる>
  14. 14. 部品プログラミング  遅延評価は計算の際にデータと制御を切り離すことが可 能。  データは制御が要求する回数だけ評価され、二つの部品は 交互に簡約を実行する。  Modularity(部品化)という特性を得られる。  素数での例: *Main> take 11 primes [2,3,5,7,11,13,17,19,23,29,31]  素数のリストを有限の上限という制約から解放し部品化している
  15. 15. 部品プログラミング 遅延評価はループの本体から 終了条件を切り離す。 これは強力な部品化の手法である。  ジョン・フューズ、「なぜ関数プログラミングは重要か」  http://www.sampou.org/haskell/article/whyfp.html
  16. 16. 部品化  椅子を作る  手続型  丸太から切り出す  遅延評価  底+背+足+のり
  17. 17. 部品化と遅延評価 仕様: replicate 5 ’*’ → "*****" 手続型でのLoop: replicate (n, x) { var ret = ""; for (var i = 0; i < n; i++) ret = push(x,ret); return ret; } 遅延評価による部品化: repeat ’*’ → [’*’,’*’,’*’,’*’,’*’, …] take 5 [’*’,’*’,’*’,’*’,’*’, …] → [’*’,’*’,’*’,’*’,’*’] → "*****" replicate n c = take n (repeat c)
  18. 18. 正格適用  いつでも遅延評価が良いとは限らない  正格評価が適していることもある。  $! :正格評価の演算子  正格評価は処理効率を上げる場合もあるが、正格の利 用は専門的な話題であり、遅延評価の振る舞いに対し て深い考察を必要とする。
  19. 19. まとめ  遅延評価はHaskellのような関数型言語の特徴です  遅延評価により、ソフトウェアの部品化を獲得できます。  遅延評価がいつも有効ではありませんが、遅延評価以 外の方法をとる場合にはその必要性に対する考察が必 要です。
  20. 20. おまけ  関数型言語以外で遅延評価は不可能か?  基本的にクロージャを構文に持つ言語であれば原則可能な はず。  C#, Ruby, ...  C#: http://msdn.microsoft.com/ja-jp/ff730144.aspx  C#はまぁ確実に関数型言語への道を。。。  開発責任者のA.ヘルスバーグが2006年に日本で明言。  Q. C#の今後の方向性は関数型に向かうのか?  A.Yes.

×