Haskell:中缀(`:`)运算符是否有左侧标识?

时间:2014-11-05 21:10:45

标签: list haskell

换句话说,在以下的过滤器实现中,我可以使用什么语法(如果有的话)代替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

3 个答案:

答案 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 : xsxs(在同一范围内)必须是不同的列表,因为它们是不同的术语。

换句话说,data类型的语义是,如果你在构造函数应用程序上模式匹配,你总是会得到相同的构造函数及其参数。例如,无论Truex是什么,这两个表达式都保证为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的答案(你可以证明)相同,效率较低 ,但它让事情有点低阶。