gpt4 book ai didi

Haskell:类型类与传递函数

转载 作者:行者123 更新时间:2023-12-02 01:26:04 25 4
gpt4 key购买 nike

在我看来,您似乎总是可以传递函数参数而不是使用类型类。例如,而不是定义相等类型类:

class Eq a where 
(==) :: a -> a -> Bool

并且在其他函数中使用它来表示类型参数必须是 Eq 的实例:
elem                    :: (Eq a) => a -> [a] -> Bool

我们不能只定义我们的 elem吗?函数而不使用类型类,而是传递一个函数参数来完成这项工作?

最佳答案

是的。这被称为“字典传递风格”。有时当我做一些特别棘手的事情时,我需要废弃一个类型类并将其转换为字典,因为字典传递更强大1,但通常很麻烦,使得概念上简单的代码看起来很复杂。我有时在不是 Haskell 的语言中使用字典传递样式来模拟类型类(但我知道这通常不像听起来那么好)。

当然,只要表现力有所不同,就需要权衡取舍。如果使用 DPS 编写,您可以以更多方式使用给定 API,但如果您不能,该 API 会获取更多信息。这在实践中出现的一种方式是 Data.Set , 这依赖于只有一个 Ord 的事实每个类型的字典。 Set存储根据 Ord 排序的元素, 如果你用一个字典构建一个集合,然后使用另一个字典插入一个元素,就像 DPS 一样,你可能会破坏 Set的不变性并导致它崩溃。这个唯一性问题可以使用 phantom existential 来缓解。 type 来标记字典,但是,再次以 API 中相当多的烦人复杂性为代价。这在 Typeable 中也以几乎相同的方式出现。 API。

唯一性位不会经常出现。类型类最擅长的是为您编写代码。例如,

catProcs :: (i -> Maybe String) -> (i -> Maybe String) -> (i -> Maybe String)
catProcs f g = f <> g

它需要两个“处理器”,它们接受一个输入并可能给出一个输出,并将它们连接起来,使 Nothing 变平,必须在 DPS 中编写如下:
catProcs f g = (<>) (funcSemi (maybeSemi listSemi)) f g

尽管我们已经在类型签名中拼出了它,但实际上我们必须再次拼出我们正在使用它的类型,即使这样也是多余的,因为编译器已经知道所有类型。因为只有一种方法可以构造给定的 Semigroup在一个类型中,编译器可以为你做这件事。当您开始定义大量参数实例并使用您的类型结构为您计算时,这具有“复合兴趣”类型效果,如 Data.Functor.* 组合器,这与 deriving via 一起使用效果很好您基本上可以在其中获得为您编写的类型的所有“标准”代数结构。

甚至不要让我开始研究 MPTC 和fundeps,它们将信息反馈给类型检查和推理。我从未尝试过将这样的东西转换为 DPS——我怀疑它会涉及传递大量类型相等性证明——但无论如何,我确信这对我的大脑来说比我感到舒服的要多得多和。

--

1除非你使用 reflection 在这种情况下,它们的功率相等——但是 reflection使用起来也很麻烦。

关于Haskell:类型类与传递函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61243217/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com