これはあなたの関数である:
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]
ことのいくつかの余分な証拠:
をあなたの例で起こっていることすべてが、その後、b
のunfoldr
での署名が、その結果、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
のような関数として)関数を書くことによって行われますが、複数の値をペアで渡す必要がある場合や便利な場合があります。あなたの例でやってください。
ヒント: 'unfoldr'の型シグネチャで' b 'を '(b、c)'に置き換え、何が起こるかを見てください。 – duplode