Функции высокого порядка в Haskell, объявление функций - PullRequest
0 голосов
/ 29 марта 2019

Я учусь на экзамен, и я запутался в этой функции. Основываясь на выводе, как я узнаю, что объявление типа функции (a -> b -> c)? Кроме того, как я могу оценить свою функцию?

zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' _ [] _ = []
zipWith' _ _ [] = []
zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys

Что я понимаю, так это то, что функции высокого порядка в haskell означают, что они принимают функцию в качестве параметра и также возвращают функцию, верно? как я могу вызвать эту функцию?

Я сделал это:

zipWith' [1..5] ['a','z','r']

но я знаю, что это неправильно, потому что я вызываю его так, как будто это обычная функция zip, которая принимает 2 списка и возвращает кортеж. Я просто запутался в объявлении типа

zipWith' :: [a] -> [b] -> [(a,b)]

1 Ответ

3 голосов
/ 29 марта 2019

Для этого ответа мы признаем, что все функции карри. То есть каждая функция имеет тип 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' (,).

...