咖喱匿名功能

时间:2016-12-08 14:15:21

标签: haskell functional-programming currying

我是Haskell的新手和函数编程,我有点困惑。为什么我不能讨论一个匿名函数,或者它是否可能?

我有以下代码:

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.

2 个答案:

答案 0 :(得分:5)

xlargestDivisible的参数,但您不需要将其作为参数传递给lambda。 lambda可以从捕获的上下文中获取x,并且只需要y作为参数。

第一个版本将部分应用的f x传递给myFilter,并且 - 给出第一个参数 - 是一元函数。

第二个版本尝试传递两个参数的lambda,而不使用部分应用程序来获得合适的函数。

在第一个示例中使用部分应用程序,或者只写一个参数的lambda(y)。

答案 1 :(得分: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的应用仍然存在!我们可以通过应用匿名函数(beta步骤)进一步简化:

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