如何正确定义像“任何”这样的函数

时间:2012-06-02 16:59:43

标签: haskell

学习Haskell,我正在尝试编写一个给定条件的函数takeIf,并且列表返回满足条件的所有列表元素。

所需输出的示例:

takeIf (>0) [] --> []
takeIf (>0) [-1, 0, 1, 2] --> [1,2]

我尝试了这个定义:

takeIf cond [] = []
takeIf cond (x:xs) = if (cond x) 
                    then x:(takeIf cond xs)
                    else []:(takeIf cond xs)

但它不起作用。

我的第一个问题是:我有

:t takeIf --> ([a] -> Bool) -> [[a]] -> [[a]]

为什么呢?为什么不:

:t takeIf --> (a -> Bool) -> [a] -> [a]

如何让这段代码生效?

这是我得到的错误:

enter image description here

如果有帮助,我正在使用ghci

3 个答案:

答案 0 :(得分:10)

[]:(takeIf cond xs)

在这里,您尝试将[]作为takeIf cond xs结果的新第一个元素。由于[]是一个列表,因此GHC推断takeIf cond xs的结果必须是列表。由于takeIf的结果与其参数的类型相同,这意味着xs也必须是列表列表。由于xxs的元素,因此x必须是列表。

好像你打算[]:意味着“不在列表中添加任何内容”,但是[]并不是什么,它是空列表。 [] : [],不会向您[]提供[[]]。同样地,[] : [1,2,3]会给你[[], 1, 2, 3] - 除了那个类型不好,所以它真正给你的是一个类型错误。

如果您不想在列表中添加任何内容,请不要在列表中添加任何内容,即只使用someList代替[] : someList

答案 1 :(得分:3)

因为sepp2k比我快 - 我只想补充一点,你可能想看看filter及其来源,这正是你尝试重新实现的功能。
这是实际的来源

filter :: (a -> Bool) -> [a] -> [a]
filter _pred []    = []
filter pred (x:xs)
  | pred x         = x : filter pred xs
  | otherwise      = filter pred xs

答案 2 :(得分:0)

替代方案是折叠,例如

filter' f = foldr go [] where 
   go x xs = if f x then x:xs else xs