Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell “deleteBy”没有最通用的类型,有什么好的理由吗?_Haskell_Frege - Fatal编程技术网

Haskell “deleteBy”没有最通用的类型,有什么好的理由吗?

Haskell “deleteBy”没有最通用的类型,有什么好的理由吗?,haskell,frege,Haskell,Frege,Haskell 2010语言报告在第20.10.1.1节中指出: deleteBy :: (a -> a -> Bool) -> a -> [a] -> [a] 事实上,在《公约》中的实施将允许: deleteBy :: (b -> a -> Bool) -> b -> [a] -> [a] 但实际上将类型限制为带有注释的前一个类型 因此,我们不能说,例如: foo = deleteBy fsteq 42 [(43, "foo"),

Haskell 2010语言报告在第20.10.1.1节中指出:

deleteBy :: (a -> a -> Bool) -> a -> [a] -> [a]
事实上,在《公约》中的实施将允许:

deleteBy :: (b -> a -> Bool) -> b -> [a] -> [a]
但实际上将类型限制为带有注释的前一个类型

因此,我们不能说,例如:

foo = deleteBy fsteq 42 [(43, "foo"), (44, "bar"), (42, "baz")] where
    fsteq a (b,_) = a == b
因为
Int
(Int,String)
不同

有什么好的理由吗

我问这个问题的原因是,如果没有充分的理由,我会在数据端口中使用更通用的类型包括
deleteBy
。但也许我忽略了什么


编辑:正如@hammar指出的,这也适用于其他xxxBy函数。

我想这是为了与其他
xxxBy
函数对称。但是,您的类型仍然是不必要的特定类型。我更喜欢这个

deleteBy :: (a -> Bool) -> [a] -> [a]
然后,您可以使用部分应用程序编写示例:

foo = deleteBy (fsteq 42) [(43, "foo"), (44, "bar"), (42, "baz")] where
    fsteq a (b,_) = a == b
英戈

在你最初的问题中,你似乎在问为什么Haskell报告会这样写。 因此,如果没有充分的理由,您可以在Frege中使用不同的定义(意味着您不关心Haskell报告的一致性)

正如哈马尔所说,它与其他xxxBy函数类似:delete使用(=),deleteBy使用(==):类型(a->a->Bool)的谓词,并假定为等价关系。虽然类型系统无法检查谓词是否真的是等价关系,但它是函数契约。所以,如果你知道xxx的意思,很容易理解xxxBy的意思。deleteBy可能不是这样,但在某些情况下,可以在谓词具有指定属性(等价关系或总顺序等)的假设下优化实现

但在你对哈马尔回答的评论中,你问更普遍的实施是否会违反报告。嗯,如果类型不同,那么它实际上就是一种违反,对吗?因为不应该根据报告编译的程序将被编译器接受。因此,它产生了一个可移植性问题:如果您的代码使用更通用的版本,那么它可能无法在另一个符合规范的实现上编译。此外,它消除了等价关系的要求

因此,如果您想要一个更通用的函数,为什么不简单地用不同的名称定义另一个函数呢?例如,deleteIf


(我想对Hammar的答案发表评论,但我不能,所以我写在这里。)

概括
deleteBy
的类型以一种非常实际的方式违反了标准:完全有效的Haskell程序由于未解决的重载而失效

下面是一个演示:

class (Num a) => Magic a where
  magic :: a -> Bool

sameMagic :: (Magic a, Magic b) => a -> b -> Bool
sameMagic a b = magic a == magic b

test :: (Magic a) => [a]
test = deleteBy sameMagic 42 [1234]
在Haskell中,这个程序的类型非常好
deleteBy
的受限类型确保
42
的类型与
1234
的类型相同。对于广义的
deleteBy
,情况并非如此,因此
42
的类型不明确,导致程序无效。(如果你想要一个较少的设计实例,考虑一个函数,它将两个<代码>积分值与 >整数< /代码>进行比较)


因此,这种受限类型可能没有充分的理由(尽管如果要推广
deleteBy
,我更喜欢哈马尔的版本,而不是你的建议),但推广它确实违反了标准,它会破坏有效的程序。

除了过滤器会删除所有相等的元素,其中deleteBy必须只删除第一个。@Ingo:Oops!你完全正确<代码>过滤器在这里不起作用。当然,有办法解决这个问题,但你看,目标是坚持标准(本例中为Haskell 2010)。问题是,如果一个人更一般一点,它是否违反了标准。@Ingo“如果一个人更一般一点,它是否违反了标准”?在技术上,是的。实际上,没有(imho)。这是我一直在寻找的那种有见地的评论。给了我一些思考的东西。这是一个非常有洞察力的答案!但是42不应该通过类型默认规则解析为
整数吗?@haskelline?