是。这被称为“字典通过风格”。有时,当我做一些特别棘手的事情时,我需要取消一个类型类并将其转换为字典,因为字典传递功能更强大1,但通常非常麻烦,使得从概念上讲简单的代码看起来相当复杂。有时,我在不是Haskell的语言中使用字典传递样式来模拟类型类(但已经了解到,通常这听起来并不像一个好主意)。
当然,每当表达能力存在差异时,就要进行权衡。如果使用DPS编写给定的API,则可以通过更多方式使用该API,但如果不这样做,则该API将获得更多信息。Data.Set
实际上,这是一种显示方式,它依赖于Ord
每个类型只有一个字典这一事实。该Set
存储其元素按照分类Ord
,如果你建立了一套与一个字典,然后插入使用不同的一个元素,将有可能DPS,你可能会打破和Set
的不变,并导致崩溃。可以使用幻像存在缓解此唯一性问题类型来标记字典,但同样,代价是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 ü nless您使用reflection
在他们成为这种情况下,在功率相当的-但reflection
也可以使用麻烦。