我需要开发自己的过滤器功能,类似于filter
在Haskell中的工作方式,但是要使用列表理解和谓词。因此,我将lcFilter (>3) [1,2,3,4,5,6,10,444,3]
放入ghci,它将打印所有大于3的数字。
我的代码基于一个我擅长的递归示例,但是我似乎无法转换为列表理解。无论我在[x | x<-xs, p]
中输入什么内容,它都会缝在一起,它总是会引发编译器错误。我知道p
部分是错误的。我已经尝试过==p
,xs==p
以及几乎所有我能想到的东西。这使我认为其他部分可能是错误的,但我真的不确定。
这是我的函数lcFilter
的代码。我不确定是部分还是全部错误,所以我要发布整个内容。
lcFilter :: (a -> Bool) -> [a] -> [a]
lcFilter _ [] = []
lcFilter p (x:xs) = [x | x<-xs, p]
如果我输入lcFilter (>3) [1,2,3,4,5]
,它应该像标准的Haskell [4,5]
函数一样打印filter
。
答案 0 :(得分:5)
就像
一样简单 [x | x <- xs, p x]
自p :: a -> Bool
和xs :: [a]
起,要获取布尔值,我们需要将该函数应用到一个参数中;通过列表理解语义,我们有了x :: a
。
类型推断的应用规则为
x :: a
p :: a -> b
-------------
p x :: b
并且您不需要模式匹配,列表理解将解决这个问题。
总的来说,是
lcFilter :: (a -> Bool) -> [a] -> [a]
lcFilter p xs = [x | x <- xs, p]
列表理解很有趣。他们遵循的一条规则是
[ ... | x <- (xs ++ ys), .... ] ===
[ ... | x <- xs, .... ] ++ [ ... | x <- ys , .... ]
因此,我们也有
[ ... | x <- ([y] ++ ys), .... ] ===
[ ... | x <- [y], .... ] ++ [ ... | x <- ys , .... ] ===
[ ...{x/y} | ....{x/y} ] ++ [ ... | x <- ys , .... ]
其中{x/y}
表示“将x
替换为y
” 。因此,列表[a,b,...,n]
根据您的定义转换为
[ a, b, ..., n ] ===>
[ a | p a] ++ [b | p b] ++ ... ++ [n | p n ]
这可以通过/作为 monads 或 monoids 的概念的很好的例证来进一步理解,但我们将其留给其他人天。 :)