2016-10-22 16 views
1

this article私はunfoldr機能でフィボナッチ数列を生成する例見つかっ読み:unfoldrのラムダ関数は、Haskellの2つの引数でどのように使用できますか?

fibs = unfoldr (\(a,b) -> Just (a,(b,a+b))) (0,1) 

をしかし、私はdocumentationを見たとき、私はunfoldr機能でラムダは一引数b取ることが判明:

unfoldr :: (b -> Maybe (a, b)) -> b -> [a] 

例このドキュメントでは、1つの引数の使用方法しか示していません。

unfoldr (\b -> if b == 0 then Nothing else Just (b, b-1)) 10 

フィボナッチの例のように、2つの引数にどのように適用できるのでしょうか? FUNCにaplied unforldr

+1

ヒント: 'unfoldr'の型シグネチャで' b 'を '(b、c)'に置き換え、何が起こるかを見てください。 – duplode

答えて

6

これはあなたの関数である:

GHCi> let foo = \(a,b) -> Just(a,(b,a+b)) 

我々は確かに二つの引数の関数として私達の頭の中にそれを解釈することができますが、限りHaskellは懸念しているとして、それが唯一の引数を取る...

foo :: Num t => (t, t) -> Maybe (t, (t, t)) 

... クラスのtの場合、(t, t)ののペアのペア。

Num t => ((t, t) -> Maybe (t, (t, t))) -> (t, t) -> [t] 

ことのいくつかの余分な証拠:

をあなたの例で起こっていることすべてが、その後、bunfoldrでの署名が、その結果、Num t => tによりNum t => (t, t)、およびaによって置き換えられているということです
GHCi> :t unfoldr (\(a,b) -> Just (a,(b,a+b))) 
unfoldr (\(a,b) -> Just (a,(b,a+b))) :: Num a => (a, a) -> [a] 

あなたの直ぐな質問に答えてください、ここでは少しばかりです。

GHCi> let foo2 a b = Just(a,(b,a+b)) 
GHCi> :t foo2 
foo2 :: Num t => t -> t -> Maybe (t, (t, t)) 

もちろんあなたも実装を書き換える必要はありませんあなたの周りにはまだfooを持っている場合、:ペアでとは対照的に、Haskellの関数に二つの引数を渡すの別の方法は、それらを個別に渡しています実際に

GHCi> let foo2 a b = foo (a, b) 
GHCi> :t foo2 
foo2 :: Num t => t -> t -> Maybe (t, (t, t)) 

、この変換 - 専門用語でをカリー化と呼ばれている - 常に可能であり、それを行うためにも機能があり...

GHCi> let foo2 = curry foo 
GHCi> :t foo2 
foo2 :: Num t => t -> t -> Maybe (t, (t, t)) 

...同様に反対方向に行くための別の一つとして:すべての点で意外かもしれない何

GHCi> :t uncurry foo2 
uncurry foo2 :: Num t => (t, t) -> Maybe (t, (t, t)) 

が、しかし、どのようにしてもfoo2をされ、さらにfooも2つの引数の関数のように見えますが、まだです1つの議論の関数!トリックはfoo2のような署名...

foo2 :: Num t => t -> t -> Maybe (t, (t, t)) 

...は一部省略し、オプションの括弧を持っているということです。この省略は、機能矢印->が右結合であるという事実を隠している。我々は彼らを追加した場合、我々が得る:

ある
foo2 :: Num t => t -> (t -> Maybe (t, (t, t))) 

は、foo2は1つの引数を取ります(それは私たちの最初の引数、である)とも一つの引数を取る別の関数(つまり、当社第二引数)を返します。


メインテイクアウトは、その後、すべてのHaskellの関数はただ一つの引数を取るということです。幸いにも、2つの引数を取るかのように機能する関数を書くのは非常に簡単です。たいていの場合、関数をカリー化して(つまり、別の関数を返すfoo2のような関数として)関数を書くことによって行われますが、複数の値をペアで渡す必要がある場合や便利な場合があります。あなたの例でやってください。

-1

まず、((A、B) - >ちょうど((B、A + B)))

機能bを返す - > [A]。これはカレーです。

その結果関数は最終結果を終了する第二引数(0、1)

に適用されます。