Haskell有太多的参数错误

时间:2015-04-10 20:45:55

标签: function haskell arguments

我正在学习Haskell。我正在尝试创建一个函数,当遇到某个函数f的参数时,它会从列表中删除整数。

deleteif :: [Int] -> (Int -> Bool) -> [Int]
deleteif x f = if x == [] 
                then [] 
                else if head x == f 
                       then deleteif((tail x) f)  
                       else [head x] ++ deleteif((tail x) f)

我收到以下错误:

  • 函数尾部应用于两个参数

  • 'deleteif'适用于太少的参数

3 个答案:

答案 0 :(得分:4)

问题是你没有使用括号来调用Haskell中的函数。所以你只需要使用

if f (head x)
   then deleteif (tail x) f
   else [head x] ++ deleteif (tail x) f 

答案 1 :(得分:2)

问题出在deleteif((tail x) f)

变为deleteif (tail x f)

所以tail得到2个参数

然后deleteif a

所以deleteif获得1个参数

你想要deleteif (tail x) f

head x == f你错了`f(头x)

您可以使用模式匹配,保护并使其更通用

deleteif :: [a] -> (a -> Bool) -> [a]
deleteif [] _ = []
deleteif (x:xs) f
    | f x       =     deleteif xs f 
    | otherwise = x : deleteif xs f

答案 2 :(得分:2)

如上所述,deleteif((tail x) f)被解析为deleteif (tail x f),这意味着tail会应用于两个参数xf,结果会然后作为deleteif的单个参数传递。你想要的是deleteif (tail x) f,它等同于(deleteif (tail x)) f以及大多数语言 1 会写deleteif(tail x, f)

这个解析顺序最初可能看起来令人困惑,但事实证明它在实践中非常有用。该技术的通用名称为Currying

  • 首先,它允许您编写密集语句而无需多个括号 - 实际上deleteif (tail x f)也可以写成deleteif $ tail x f
  • 更重要的是,因为参数不需要被“封装”在单个元组中,所以您不需要一次性提供所有参数,而是在申请时自动获取部分应用只有一个论点。例如,你可以使用这样的函数:deleteif (>4) [1,3,7,5,2,9,7]来产生[7,5,9,7]。这可以通过将函数 2 >部分应用于4来实现,只留下一个可用于过滤列表的单参数函数。

1 的确,这种风格在Haskell中也是可能的:只需将这些多参数函数的签名写为deleteif :: ([Int], Int->Bool) -> [Int]。或者写uncurry deleteif (tail x, f)。但是你最好习惯咖喱风格!

2 实际上,>是一个中缀,它的行为有点不同 - 你可以将它部分地应用到任何一方,即你也可以写deleteif (4>) [1,3,7,5,2,9,7]以获取[1,3,2]