Haskell 如何正确定义一个函数,如;任何;

Haskell 如何正确定义一个函数,如;任何;,haskell,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)

研究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]
我怎样才能让这个代码工作

这是我得到的错误:

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

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

似乎您打算让
[]:
表示“在列表中不添加任何内容”,但
[]
不是什么,而是空列表<代码>[]:[],它不是给你
[]
,而是给你
[[]]
。同样地,
[]:[1,2,3]
会给你
[[],1,2,3]
——除了那不是很好的类型,所以它真正给你的是一个类型错误


如果您不想在列表中预先添加任何内容,请不要在列表中预先添加任何内容,即只需使用
someList
而不是
[]:someList

,因为sepp2k比我快-我只想补充一点,您可能想看看它的源代码,它正是您尝试重新实现的函数。
这是实际的来源

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

另一种是褶皱,例如

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

请注意,
takeIf
在名称
filter
下更为常见(并且已经定义)。是的,就像在Scheme中一样。我试图了解如何操作。好的,谢谢。按照您的指示,我还得到了另一种解决方案:使用
[]++someList
。实际上我不知道,但您为什么要这样做
[]+
。这是一种添加0的方法,编译器(希望)优化了它。我完全同意您的意见。这只是将空列表与另一个列表连接起来的方法,但您的建议要好得多。+1用于指出函数已经存在。但也要考虑到一种学习方式是编写现有功能的次优版本:Dthanks为+1,通过重写自己的IHOH学习是最有价值和令人恼火的事情之一,但之后/在过程中,你应该看看“亲”的人是如何实现你想要达到的东西的。这就是我想补充答案的原因。