2017-01-31 21 views
2
module Tf0 where 

all' :: (a -> Bool) -> [a] -> Bool 
all' p = foldr (&&) True . map p 

main :: IO() 

xs = [1,3,5,7,9] 
xs1 = [1,3,11,4,15] 

k1 = all' (<10) xs 
k2 = all' (<10) xs1 
k3 = all' (<10) 

main = print k1 

Вопросы:Определение функции Haskell, отсутствующий аргумент?

  1. В определении функции (all' p = foldr (&&) True . map p) нет списка в качестве вклада в то время как функция типа показывает список как вход ([a]), но пытается проверить функцию (см bellow k1, k2, k3) показывает, что необходим список.

  2. Как определить функцию без списка?

+1

Запись 'f x = g x. h x' то же, что и запись 'f x y = g x (h x y)', по определению оператора композиции '.'. Первый стиль называется «бессмысленным стилем» (или, в шутку, без точечного стиля). – chi

+0

Одно слово: каррирование. – chepner

ответ

4

Одним из основных аспектов Haskell является то, что концептуально функция всегда принимает один аргумент. Действительно, например, взять функцию (+):

(+) :: Int -> Int -> Int 

(технически это (+) :: Num a => a -> a -> a, но давайте не усложнять).

Теперь вы можете утверждать, что (+) принимает два аргумента, но концептуально он принимает один аргумент. Действительно: подпись фактически

(+) :: Int -> (Int -> Int) 

Таким образом, вы кормить его один целое и теперь она возвращает функцию, например:

(+) 5 :: Int -> Int 

Так у вас есть, давая ему 5, построенный функция, которая добавит 5 к заданному операнду (снова функция, которая принимает один аргумент).

Применяя это к вашему вопросу, подпись all' фактически:

all' :: (a -> Bool) -> ([a] -> Bool) 

Так что, если вы применяете all' с одним аргументом, он возвращает функцию, которая отображает список [a] к Bool. Скажем, ради аргумента, что мы устанавливаем p в \_ -> True, то мы возвращаем:

foldr (&&) True . map (\_ -> True) :: [a] -> Bool 

так действительно является функцией, которая принимает список [a] и отображает его на Bool. В следующей фазе вы применяете список к , который (возврат) функции.

Другими словами, функциональное программирование можно рассматривать как длинную цепочку, специализирующую функцию дальше и дальше, пока она не будет полностью заземлена и не будет оценена.

Haskell предоставляет только это элегантным способом, так что вам не нужно думать о функциях, генерирующих функции. Но концептуально это происходит все время.Учитывая, вы хотите реализовать функцию f :: a -> b -> c, вы можете сделать это, как:

f x y = g (x+1) y 

g :: a -> b -> c), но вы можете также принять решение оставить параметр вне, и определить его как:

поскольку g (x+1) вернет функцию, которая может применяться с y в конце концов.

+1

Я бы избегал раздела '(5+)' для этого, поскольку он использует специальный синтаксис и вместо этого использует простое приложение '(+) 5', которое следует духу аргумента. – chi

+0

@chi: это действительно хорошее предложение: изменено. Благодарю. –

+0

Спасибо за ваши хорошие объяснения, однако я хотел бы получить ответ на следующее: Учитывая (из вашего примера, что две (разные?) Функции: fxy = g (x + 1) y и fx = g (x + 1), как вторая функция (fx = g (x + 1)) «Знает», что ожидается второй параметр (y)? – Atir

Смежные вопросы