使用列表理解的谓词自定义过滤器功能

时间:2019-05-20 06:31:49

标签: haskell filter list-comprehension higher-order-functions

我需要开发自己的过滤器功能,类似于filter在Haskell中的工作方式,但是要使用列表理解和谓词。因此,我将lcFilter (>3) [1,2,3,4,5,6,10,444,3]放入ghci,它将打印所有大于3的数字。

我的代码基于一个我擅长的递归示例,但是我似乎无法转换为列表理解。无论我在[x | x<-xs, p]中输入什么内容,它都会缝在一起,它总是会引发编译器错误。我知道p部分是错误的。我已经尝试过==pxs==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

1 个答案:

答案 0 :(得分:5)

就像

一样简单
      [x | x <- xs, p x]

p :: a -> Boolxs :: [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 的概念的很好的例证来进一步理解,但我们将其留给其他人天。 :)