换句话说,在以下的过滤器实现中,我可以使用什么语法(如果有的话)代替XXX
:
filter' :: (a -> Bool) -> [a] -> [a]
filter' _ [] = []
filter' f (x:xs) =
let n = if f x then x else XXX
in n:(filter' f xs)
我已经意识到以下替代实现(它是递归的,只是预先添加),但如果中缀运算符具有LHS身份,它仍然会很奇怪。
filter' :: (a -> Bool) -> [a] -> [a]
filter' _ [] = []
filter' f (x:xs)
| f x = x:(filter' f xs)
| otherwise = filter' f xs
答案 0 :(得分:12)
没有。这可以看出因为
ghci> length (undefined : [])
1
所以无论你放在哪个元素,你总会得到1的长度。
这句话怎么样:
filter' f (x:xs) =
let n = if f x then (x:) else id
in n (filter' f xs)
答案 1 :(得分:2)
手波警报:以下严格来说是谎言(因为undefined
等),但它仍然是一个有用的想法。
使用Haskell data
声明定义的类型的一个关键属性是自由:data
类型的值集与的同构集同构>该类型的正规形式术语(完全评估的表达式)。如果该类型的两个术语不同,则它们具有不同的值。
由此可见x : xs
和xs
(在同一范围内)必须是不同的列表,因为它们是不同的术语。
换句话说,data
类型的语义是,如果你在构造函数应用程序上模式匹配,你总是会得到相同的构造函数及其参数。例如,无论True
和x
是什么,这两个表达式都保证为xs
:
case [] of
[] -> True
x:xs -> False
case (x:xs) of
[] -> False
x':xs' -> x == x' && xs == xs'
您要查找的左侧身份值将是此处第二个表达式的反例。因此,没有这样的价值。
答案 2 :(得分:2)
没有,但++
具有身份,即[]
。所以这也可行:
filter' _ [] = []
filter' f (x:xs) =
let n = if f x then [x] else []
in n ++ (filter' f xs)
这与@ luqui的答案(你可以证明)相同,效率较低 ,但它让事情有点低阶。