haskell超入門 part.2

33

Upload: yuichi-watanabe

Post on 14-Dec-2014

883 views

Category:

Technology


5 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Haskell超入門 Part.2
Page 2: Haskell超入門 Part.2

Nabe

Twitter / Facebook / Hatena

nabe256

Page 3: Haskell超入門 Part.2
Page 4: Haskell超入門 Part.2

Haskellにおけるクロージャ

Page 5: Haskell超入門 Part.2

Twitterの某発言から

› @rizumita: @nabetaro 関数型言語とかクロージャとかが聞きたいです。話せる人がどれだけいるか分かりませんが…

› @nabetaro: 関数型言語というと、話したい人がいるんじゃないかな〜(他力本願)

› @nabe256: Haskellで発表出来るかなぁ・・・

Page 6: Haskell超入門 Part.2

Twitterの某発言から

› @rizumita: @nabetaro 関数型言語とかクロージャとかが聞きたいです。話せる人がどれだけいるか分かりませんが…

› @nabetaro: 関数型言語というと、話したい人がいるんじゃないかな〜(他力本願)

› @nabe256: Haskellで発表出来るかなぁ・・・

そんな餌で俺様が釣られクマ――(AA略

Page 7: Haskell超入門 Part.2

でもクロージャは

ふいんき(←なぜか変換できない)

だけしか知らない。

なので、

関数型言語Haskellにおける

クロージャについて

それっぽい解説を。

Page 8: Haskell超入門 Part.2

Haskellは初心者レベルです。

クロージャは名前だけなら知ってるというレベルです。

色々調べてみましたが、間違いが含まれている可能性が大いにあります。

おかしな所があったら是非教えてください。

Page 9: Haskell超入門 Part.2

クロージャ(クロージャー、closure、閉包)はプログラミング言語における関数の一種。引数以外の変数を実行時の環境ではなく、自身が定義された環境(静的スコープ)において解決することを特徴とする。関数とそれを評価する環境のペアであるともいえる。

(by Wikipedia)

Page 10: Haskell超入門 Part.2

なにゆーてんの?

Page 11: Haskell超入門 Part.2

典型的には、クロージャはある関数全体が他の関数(以下、エンクロージャ)の内部で宣言されたときに発生し、内部の関数はエンクロージャのローカル変数(レキシカル変数)を参照する。実行時に外部の関数が実行された際、クロージャが形成される。クロージャは内部の関数のコードとエンクロージャのスコープ内の必要なすべての変数への参照からなる。

(by Wikipedia)

Page 12: Haskell超入門 Part.2

なにそれ。おいしいの?

Page 13: Haskell超入門 Part.2

クロージャは

関数内で一時的な関数を作るための仕組み。

Page 14: Haskell超入門 Part.2

言葉で説明しても難しいので、

サンプルを作って考えてみる。

普通の書き方から。

Page 15: Haskell超入門 Part.2

割り算を計算する関数。 div :: Double -> Double -> Double

div x y = x / y

引数を二つ取り、値を返す関数。

使い方 ghci> div 4 3

1.3333333333333333

Page 16: Haskell超入門 Part.2

式変形をしてみる。

div’ x y = f

where

f = x / y

使い方 ghci> div’ 4 3

1.3333333333333333

Page 17: Haskell超入門 Part.2

div’ x y = f

where

f = x / y

fは外側のdiv’関数(エンクロージャ)の中で

定義された一時関数(クロージャ)になる。

クロージャはエンクロージャより外からは

参照出来ない。

fからは、エンクロージャの値(x,y)を参照することが出来る。

Page 18: Haskell超入門 Part.2

引数付きの関数も作成可能。

div’’ x y = f x y

where

f a b = a / b

使い方 ghci> div’’ 4 3

1.3333333333333333

Page 19: Haskell超入門 Part.2

二次方程式の解の公式

roots a b c =

((-b + sqrt(b*b – 4*a*c)) / (2*a),

(-b – sqrt(b*b – 4*a*c)) / (2*a))

Page 20: Haskell超入門 Part.2

roots a b c =

((-b + sqrt(b*b – 4*a*c)) / (2*a),

(-b – sqrt(b*b – 4*a*c)) / (2*a))

roots’ a b c =

((-b + det) / (2*a),

(-b – det) / (2*a))

where det = sqrt(b*b – 4*a*c)

Page 21: Haskell超入門 Part.2

roots a b c =

((-b + sqrt(b*b – 4*a*c)) / (2*a),

(-b – sqrt(b*b – 4*a*c)) / (2*a))

roots’ a b c =

((-b + det) / (2*a),

(-b – det) / (2*a))

where det = sqrt(b*b – 4*a*c)

共通部分をひとまとめにして、

見やすくする事が可能。

Page 22: Haskell超入門 Part.2

Haskellではwhereとほぼ同じ機能を

持つものとしてletというものがある。

whereの前と後を入れ替えたようなもの

なので、読みやすさや状況によって

使い分ける。

恐らくwhereの方が一般的に使われている。

同じ名前で関数定義すると、実際にどちらが使われているのか分かりづらい。

混ぜるな危険。

Page 23: Haskell超入門 Part.2

引数の一部だけ指定して定義。

div x y = x / y

div4 = div 4

ghci> div4 3

1.3333333333333333

値を固定した関数を作る事が出来る。

これもクロージャの一種。

Page 24: Haskell超入門 Part.2

定義が必ずしも必要でない書き方。

div’’’ = ¥x -> ¥y -> x / y

使い方 ghci> div’’’ 4 3

1.3333333333333333

ghci> (¥x -> ¥y -> x / y) 4 3

1.3333333333333333

同じような事が出来る。

使い方によってはこれもクロージャの一種。

Page 25: Haskell超入門 Part.2

言語によってクロージャの定義が

異なったりしています。

解説者によっても

ばらつきがあるように見えます。

Don’t think. Feel!

Page 26: Haskell超入門 Part.2

引数を二つ取り、値を返す関数について。

先程の割り算を計算する関数。 div :: Double -> Double -> Double

div x y = x / y

Page 27: Haskell超入門 Part.2

引数を二つ取り、値を返す関数について。

正確には、

引数を一つ取り、

[引数を一つ取り、値を返す関数]

を返す関数。

正しい意味を解説すると難しい話に

なるので、ここでは説明はしない。

Page 28: Haskell超入門 Part.2

引数や返り値について

もう少し詳しく知りたい人は

「Haskell超入門 Part.1」を見てみると

もしかしたらわかるかも。

確実に理解したい方は、

もっと詳しく丁寧に説明しているサイトが

沢山ありますのでとりあえずググれ。

Page 29: Haskell超入門 Part.2

先程のdiv関数に小細工。

div x y = x / y

div’’ x y = (/) x y

div’’’ x = (/) x

div’’’’ = (/)

Page 30: Haskell超入門 Part.2

式変形によって値を消すことが可能。

値が無い状態をポイントフリーと呼ぶ。

(ポイント=値、変数、引数)

いろんなテクニックがあるので奥が深い。

ポイントフリーと部分適用を使うと

関数合成が自由に行える。

ポイントフリーに限らず、式変形は面白い。

詳細はとりあえずググれ。

Page 31: Haskell超入門 Part.2

Q.こんな時、どんな書き方をすれば良いか

わからないの。

Page 32: Haskell超入門 Part.2

Q.こんな時、どんな書き方をすれば良いか

わからないの。

A.ググればいいと思うよ。

Page 33: Haskell超入門 Part.2

クロージャの説明が少なかったので

調べるのに苦労しました。

わかりやすいサンプルが作れなかったのが残念。

Haskellは難しいけど楽しいです。