2012-01-27 17 views
9

怠惰に関連して機能の構成がどのように機能するか説明したり、いくつかのリソースを与えてもらえますか?怠惰と機能の構成(haskell、erlang)

たとえば、ハスケルでfilter (/='W') . map toUpper $ "justaword"はどのように動作するのですか?それは、怠け者ではないerlangのカウンターパートと比べますか?

答えて

13

別の文字が要求される(または終了の通知がある)たびに、次の文字(存在する場合)が大文字にマップされ、それが 'W'と比較されます。 take 1ようnullようなクエリや機能のために、それ以上の作業が行われないよう

filter (/= 'W') . map toUpper $ "justaword" 
~> filter (/= 'W') (toUpper 'j' : map toUpper "ustaword") 
~> filter (/= 'W') ('J' : map toUpper "ustaword") 
~> 'J' : filter (/= 'W') (map toUpper "ustaword") 

は今、最初の文字は、使用可能です。消費者によってより多くの文字が要求されると、文字列の最後に達するまで順次に生成されます。

例:

Prelude Data.Char> take 10 . filter (/= 'W') . map toUpper $ repeat 't' 
"TTTTTTTTTT" 

repeatは無限リストを生成し、しかし限りのみ有限の一部が消費され、計算は、有限の時間で終了します。ただし、take 10 . filter (/= 'W') . map toUpper $ repeat 'w'は、生成された文字のいずれもfilterを通過してtake 10に届かないため、終了しません。

+0

偉大なresponeありがとう:)それは厳格な言語で(怠惰をシミュレートせずに)このコードを書くことは可能ですか?または、厳密な言語では、リストはマップのために1回、フィルターのために1回、最初から2回、トラバースされますか? – Adi

+1

@Adi:はい、2つのリストトラバーサルがあります。 mapは新しい中間リストを返します。これはフィルタに渡され、それは渡され、さらに別のリストを返します。 – newacct

+5

厳密(むしろ熱心な)言語では、同じ動作を得るために怠惰をシミュレートする必要があります。いくつかの言語は他の言語よりも簡単ですが、私はC言語よりもerlangやF#でそれをやっています(C言語を知っていますが、erlangやF#はほとんどありません)。 2つのトラバースがあるか、熱心な言語のものであるかは、コンパイラによって異なります。原則として、フィルタとマップは融合できますが、一般に、コンパイラはマップされた関数の純度とフィルタ述語を証明する必要があります。だから私はほとんどの場合、2つのトラバーサルを期待して、証拠は難しいです。 –

関連する問題