【问题标题】:Why Haskell's Data.List.deleteBy takes in input a comparison function (a -> a -> Bool) and a value instead of a predicate (a -> Bool)?为什么 Haskell 的 Data.List.deleteBy 输入一个比较函数(a -> a -> Bool)和一个值而不是谓词(a -> Bool)?
【发布时间】:2014-04-10 23:06:13
【问题描述】:

我有一个关于 Data.List 和deleteBy 签名的问题。理想情况下,此函数应输入谓词并删除谓词为真的第一个元素。比如:

deleteBy :: (a -> Bool) -> [a] -> [a]
deleteBy p = go
    where go []                   = []
          go (x:xs) | p x         = xs
                    | otherwise   = x:go xs

相反,库中定义的函数同时接受谓词和值:

deleteBy                :: (a -> a -> Bool) -> a -> [a] -> [a]
deleteBy _  _ []        = []
deleteBy eq x (y:ys)    = if x `eq` y then ys else y : deleteBy eq x ys

很容易看出eq 始终与x 作为第一个参数一起使用,x 固定在deleteBy 中,因此没有理由同时使用eqx 而不是@ 987654331@。相反,通过对单个元素使用谓词,您可以传递不比较两个值的谓词,例如适用于 a 类型的一部分的函数或像 cons true 这样的普通函数。我的问题是:为什么deleteBy是这样实现的?

【问题讨论】:

标签: haskell


【解决方案1】:

deleteBy 函数是delete 的泛化,所以先看看delete 会很有帮助。

delete :: Eq a => a -> [a] -> [a]

delete 获取一个值 Eq a => a,然后使用 Eq 实例中的 (==)[a] 中删除该值的第一次出现。

Data.List 中的所有*By 函数一样,Eq 约束被删除,程序员需要提供自己的替换(==) 函数。

因此,从delete 中删除Eq 约束并将其替换为(==) 的类型,即a -> a -> Bool,得到deleteBy 的类型。

换句话说,这是为了与Data.List 中的其余*By 操作保持一致。

【讨论】:

  • 这一切都表明deleteBy 应该以更一般的功能给出。
【解决方案2】:

正如 cdk 和其他人指出的那样。就是对等式谓词进行泛化。

您要求的功能是“删除列表中与该谓词匹配的元素”。这更类似于单个元素filter

deleteBy 函数是“删除元素 x,但使用此比较运算符而不是 (==)”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-19
    • 2018-03-26
    • 2012-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多