Это ваша функция:
GHCi> let foo = \(a,b) -> Just(a,(b,a+b))
В то время как мы можем, конечно, интерпретировать его в наших головах как функция двух аргументов, насколько это касается Haskell он принимает только один аргумент ...
foo :: Num t => (t, t) -> Maybe (t, (t, t))
... a пара типа (t, t)
для некоторых t
в категории Num
. Все, что происходит в вашем примере, то, является то, что b
в подписи unfoldr
«s заменяется Num t => (t, t)
и a
по Num t => t
, в результате чего:
Num t => ((t, t) -> Maybe (t, (t, t))) -> (t, t) -> [t]
Некоторые дополнительные доказательства того, что:
GHCi> :t unfoldr (\(a,b) -> Just (a,(b,a+b)))
unfoldr (\(a,b) -> Just (a,(b,a+b))) :: Num a => (a, a) -> [a]
С вашим немедленным ответом на вопрос, вот небольшое отступление. Другой способ передачи двух аргументов функции Haskell проходит их по отдельности, а не в паре:
GHCi> let foo2 a b = Just(a,(b,a+b))
GHCi> :t foo2
foo2 :: Num t => t -> t -> Maybe (t, (t, t))
Очевидно, что если вы до сих пор foo
вокруг вас даже не нужно переписать реализацию:
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
, по-прежнему является функция одного аргумента! Хитрость заключается в том, что подпись, как у foo2
...
foo2 :: Num t => t -> t -> Maybe (t, (t, t))
... имеет некоторые опущены, дополнительные круглые скобки. Упущение скрывает тот факт, что функция arrow, ->
, является право-ассоциативной. Если мы добавим их, мы получаем:
foo2 :: Num t => t -> (t -> Maybe (t, (t, t)))
То есть, foo2
принимает один аргумент (то есть, наш первый аргумент) и возвращает другую функцию, которая также принимает один аргумент (то есть, нашего второго аргумента).
Основной вынос, то, что все функции Haskell принимают только один аргумент. К счастью, очень легко писать функции, которые работают так, как будто они принимают два аргумента. Чаще всего это делается путем записи функции в карри (например, как функция foo2
, которая возвращает другую функцию), но иногда необходимо или удобно передавать несколько значений в паре, как это было необходимо сделайте в своем примере.
Подсказка: замените 'b' на' (b, c) 'в сигнатуре типа' unfoldr' и посмотрим, что произойдет. – duplode