2016-12-08 2 views
1

Я новичок в программировании Haskell и функции, и я немного смущен. Почему я не могу выполнить анонимную функцию, или это возможно?Curry Анонимная функция

я следующий кусок кода:

largestDivisible :: (Integral a) => a -> a 
largestDivisible x 
    | x <= 0 = error "NOT A VALID VALUE" 
    | otherwise = head (myFilter (f x) [x-1, x-2..1]) 
    where f x y= x `mod` y == 0 

Когда я пытаюсь написать это:

largestDivisible :: (Integral a) => a -> a 
largestDivisible x 
    | x <= 0 = error "NOT A VALID VALUE" 
    | otherwise = head (myFilter (\ x y = x `mod` y == 0) [x-1, x-2..1]) 

Затем я получаю следующее сообщение об ошибке при попытке загрузить его в GHCi Я получаю следующее сообщение об ошибке:

ListStuff.hs:85:35: error: 
• Couldn't match expected type ‘Bool’ with actual type ‘a -> Bool’ 
• The lambda expression ‘\ x y -> (mod x y == 0)’ 
    has two arguments, 
    but its type ‘a -> Bool’ has only one 
    In the first argument of ‘myFilter’, namely 
    ‘(\ x y -> (mod x y == 0))’ 
    In the first argument of ‘head’, namely 
    ‘(myFilter (\ x y -> (mod x y == 0)) [x - 1, x - 2 .. 1])’ 
• Relevant bindings include 
    x :: a (bound at ListStuff.hs:83:19) 
    largestDivisible' :: a -> a (bound at ListStuff.hs:83:1) 
Failed, modules loaded: none. 
+0

Почему вы использовали 'myFilter' вместо' filter'? И я считаю более подходящим использовать 'find' вместо' filter'. – freestyle

ответ

5

Код

| otherwise = head (myFilter (f x) [x-1, x-2..1]) 
where f x y= x `mod` y == 0 

эквивалентно

| otherwise = head (myFilter (f x) [x-1, x-2..1]) 
where f = \x y -> x `mod` y == 0 

что эквивалентно

| otherwise = head (myFilter ((\x y -> x `mod` y == 0) x) [x-1, x-2..1]) 
                -- ^^^ 

Обратите внимание, что применение x все еще остается там! Мы можем дополнительно упростить использование анонимной функции (шаг бета):

| otherwise = head (myFilter (\y -> x `mod` y == 0) [x-1, x-2..1]) 
+0

Вам второй фрагмент кода: имеет ли пробел дело? Есть ли разница в написании '\ x ...' или '\ x ...'? Хорошо, думаю, я понял. В третьем фрагменте кода я создаю функцию, к которой я передаю x (x, который вы отметили), а затем передаю список. Спасибо тебе за это! Очевидно, что четвертый фрагмент кода будет «лучшим». –

+0

@SparkMonkay '\ x' - это то же самое, что и' \ x'. Конечно, пространство внутри '\ x y' имеет значение, иначе' \ xy' принимает переменную 'xy' в качестве аргумента. – chi

+0

Вот что я имею в виду: '\ x y z' совпадает с' \ x y z'. –

5

x является аргументом largestDivisible, но вам не нужно передавать его в качестве аргумента для вашей лямбды. Лямбда может получить x из захваченного контекста, и в качестве аргумента требуется только y.

Первая версия пропускает частично примененную f x до myFilter, а это - с первым аргументом - является унарной функцией.

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

Либо используйте частичное приложение, как в первом примере, либо просто напишите лямбда одного аргумента (y).

+0

Я вижу это, спасибо. Печально, что я не взял x из контекста и применил его к функции. –

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