2012-01-31 14 views
13

私にとってクロージャは、同じ場所にあるデータを持つ(入れ子?)関数です。クローズ(ハスケル)

ハスケルにソフトウェアを書き込んで後で見ると、意図せずに作成したクロージャが頻繁に見つかることがあります。

私はこの権利を自分自身で得ることはできません。どのような状況で私は意図的にクロージャをコード化したいですか?結局のところ、すべての例では、同じ場所にあるデータの量は自明ではなく、実際には(意図的な)作成を正当化するようなものではないようです。意図的にクロージャを作成する際に私をサポートするHaskellモジュールがありますか?それらを地図に保存する?

+4

興味深い質問...意図せずに作成されたクロージャによって、正確にはどういう意味ですか? –

+0

@Jonathan Sterlingはほとんどの場合、ネストされた関数を作成します。通常、dflemstrは常に「クロージャー」を作成していると指摘しているため、それらは「クロージャー」と呼ばれる基準を満たします。 –

+0

これは、haskellに名前を持つ価値のある概念でもありません。 curryingと部分的な適用を理解していますか、型の署名 'Int - > Int - > Int'が' Int->(Int-> Int) 'に相当するのはどうですか? – jberryman

答えて

25

ハスケルでは、関数は言語の本質的な部分です。主にハスケルはLambda Calculusに基づいています。

ラムダ微積分には、「自由変数」を持つ関数があります。つまり、直接変数として渡されなかった変数が使用されます。自由変数を持つ関数は、この場合「クロージャ」と呼ばれるものです。

自由変数を持つ関数はLCで非常に一般的であるため、Haskell言語の不可欠な部分も形成します。たとえば、ときにこれを書く:でも

f a b = \ c -> a * b + c 

...または:

f a b c = a * b + c 

...あなたも、まったく同じ結果と、これを書くことができ

f a b = let product = a * b in \ c -> product + c 

...さらに同等の変更:

f a = \ b -> let product = a * b in \ c -> product + c 

これはHaskellが本質的にフリー変数を持つ関数をすべてというように作成するため、常にクロージャが作成されるからです。これらの中には、コンパイラによって最適化されているものもありますが、自分で発見することができるよりも多くのクロージャが使用されることは想定しても安全です。

したがって、クロージャーの位置を確認しないでください。彼らはハスケルで特別なものではなく、常に使用されています。

+0

すべてが理解されています。まだ私には分かりません:私はハスケルで(a)意図的にクロージャを作成し、(b)マップに格納し、(c)私がterm_to_binary()でErlangでできるのと同じように、 –

+0

@JFritschでは、マップに関数を簡単に格納することができ、「意図的にクロージャを作成する」ことができます。 Haskellはクロージャと通常の関数を区別していないので、通常の関数をマップに格納するだけで簡単です。しかし、関数をシリアライズすることは非常に難しく、GHCには実験的なサポートがありますが、それを実行する信頼できる方法はありません。変数は、例えば、クロージャがそのような変数に依存している場合、実際にはそれをビットストリームに変換することはできません。 – dflemstr

+0

Data.Binaryで結果のマップをシリアル化することはできませんか? –

3

通常、テーブルや関数を事前計算する必要がある場合や、大量のデータを必要とする関数がある場合は、それがクロージャとして行われます。先日私のAIの宿題では、多くのサンプルから学び、(Point -> Bool)関数をポップアウトしたことを書きましたが、その関数は学習プロセスから蓄積した多くのデータに依存しなければなりませんでした。

+0

plsで、サンプルコードをもう少し詳しく説明できますか? –