我认为类型类areHaskell 的重要组成部分。
它们是 Haskell 的一部分,使其成为我所知道的最容易重构的语言,并且它们对于您能够推断代码的正确性来说是一笔巨大的财富。
那么,我们来谈谈字典传递。
现在,任何类型的字典传递都是对传统面向对象语言的状况的重大改进。我们知道如何在 C++ 中使用 vtable 进行 OOP。然而,在 OOP 语言中,vtable 是“对象的一部分”。将 vtable 与对象融合会迫使你的代码变成一种形式,在这种形式中,你对谁可以用新功能扩展核心类型有严格的纪律,实际上只有类的原始作者必须将其他人想要融入的所有东西结合起来他们的类型。这导致了“熔岩流代码”和各种其他设计反模式等。
像 C# 这样的语言让你能够侵入扩展方法来伪造新的东西,而 scala 等语言的“特征”和其他语言的多重继承也让你可以委托一些工作,但它们只是部分解决方案。
当你将 vtable 从它们操作的对象中分离出来时,你会得到一股令人兴奋的力量。现在您可以将它们传递到任何您想要的地方,但是当然您需要命名它们并谈论它们。围绕模块/函子的 ML 规则和显式字典传递风格采用了这种方法。
类型类采取稍微不同的策略。我们依赖于给定类型的类型类实例的唯一性,并且主要是这种选择,它允许我们摆脱这种简单的核心数据类型。
Why?
因为我们可以将字典的使用转移到使用站点,而不必将它们与数据类型一起携带我们可以相信,当我们这样做时,代码的行为没有任何改变.
将代码机械翻译为更复杂的手动传递的字典会失去此类字典在给定类型下的唯一性。现在,在程序的不同点传递字典会导致程序具有截然不同的行为。您可能需要也可能不需要记住构造您的数据类型所用的字典,如果您想根据您的参数进行条件行为,那么您将遭遇不幸。
对于简单的例子,例如Set
您可以通过手动词典翻译来摆脱困境。价格好像没那么高。你必须在字典中烘焙,比如说,你想如何排序Set
当你制作这个物体然后insert
/lookup
,只会保留您的选择。这可能是你可以承受的成本。当你联合两个Set
当然,现在您收到的订单还是悬而未决的。也许你把较小的插入到较大的中,但是顺序会随意改变,所以你必须把左边的插入到右边,或者记录这种随意的行为。为了“灵活性”,您现在被迫采用性能不佳的解决方案。
But Set
这是一个简单的例子。在那里,您可以将索引烘焙到有关您正在使用的实例的类型中,只涉及一个类。当您想要更复杂的行为时会发生什么?我们用 Haskell 做的事情之一就是使用 monad 转换器。现在你有lots大量的实例漂浮在周围——而你没有一个好的地方来存储它们,MonadReader
, MonadWriter
, MonadState
等等都可以根据底层 monad 有条件地应用。当您吊起并更换它时会发生什么,现在不同的事情可能适用或可能不适用?
为此携带显式字典需要大量工作,没有一个好的地方来存储它们,并且您要求用户采用全局程序转换来采用这种做法。
这些都是类型类可以轻松完成的事情。
我相信你应该将它们用于所有事情吗?
不是由一个长镜头。
但我不同意这里的其他回复,认为它们对 Haskell 来说是无关紧要的。
Haskell 是唯一提供它们的语言,并且它们至少对于my用这种语言思考的能力,这是我将 Haskell 视为家的一个重要原因。
我确实同意这里的一些事情,当有法律并且选择明确时使用类型类。
然而,我会质疑,如果你没有法律或者选择不明确,你可能对如何建模问题域了解不够,并且应该寻找你想要的东西can将其放入类型类模型中,甚至可能放入现有的抽象中——当您最终找到该解决方案时,您会发现可以轻松地重用它。