Для этого ответа мы признаем, что все функции карри. То есть каждая функция имеет тип a -> b
, где a
и b
- некоторый тип.
Функция высшего порядка - это функция, тип которой включает функцию для либо ее аргумент или возвращаемый тип. Возвращать значения легко: это любая функция, о которой вы обычно думаете, что она принимает более одного аргумента:
take :: Int -> [a] -> [a]
. Он принимает Int
и возвращает (полиморфную) функцию, которая берет список и возвращает список.
map :: (a -> b) -> [a] -> [b]
. Он принимает функцию (буквально любая функция) и возвращает функцию из списков в списки. Типы возвращаемого значения определяются типом аргумента.
Функции высшего порядка, которые принимают функцию и возвращают что-то, что не является функцией, на самом деле встречаются довольно редко. Возможно, комментатор укажет на очевидный случай, который я пропускаю, но до тех пор рассмотрим fix :: (a -> a) -> a
.
Теперь zipWith'
является примером функции высшего порядка, аргумент которой сам должен быть функцией высшего порядка. Общий тип a -> b
может объединяться с обычной функцией, такой как ord :: Char -> Int
(a ~ Char
и b ~ Int
), а также с функцией более высокого порядка, такой как (+)
(с a ~ Num t => t
и b ~ Num t => t -> t
. Тип a -> b -> c
будет только объединяться с функциями более высокого порядка. a
может быть или не быть типом функции, но b -> c
является явным типом функции.
Это означает, что как только вы примените zipWith'
к какой-либо функции более высокого порядка, вывод типа даст вам больше информации о том, какие типы [a]
, [b]
и [c]
должны быть в результирующей функции.
zipWith' (+)
говорит вам, что a ~ b ~ c ~ Num t => [t]
.
zipWith' (,)
говорит вам, что a
и b
все еще не ограничены, но c ~ (a, b)
zipWith' (:)
говорит вам, что a
неограничен, но b ~ c ~ [a]
.
Также может помочь, если вы считаете, что zip :: [a] -> [b] -> [(a,b)]
можно определить как zip = zipWith' (,)
.