6

我不明白为什么FingerTree用 type class 实现Measured

我正在尝试实现一个默认度量与幺半群相同的幺半群序列,所以我写了以下内容。

instance Monoid a => Measured (Sum Int, a) a where
  measure x = (Sum 1, x)

当然,由于FingerTree它本身是 a Measured,这是不可能的,因为我们会得到类型类重叠。

什么时候把这个单一的函数抽象成一个类型类才有意义?为什么我们不能只定义FingerTree以便我们可以将度量函数提供给构造函数?

也很高兴知道是否有办法克服这个问题。我每次都可以为我的特定用例定义一个新实例,但也许有更好的方法。

4

1 回答 1

4

这是类型类函数解析和“直接”函数解析之间普遍摩擦的一个实例。正如您在此处指出的那样,有很多时候支持直接,但通常可以说明类型类实例必须支持的特定法律,人们发现使用类型类解析是有意义的。

我认为不可能有一个更好的“正确”答案,但是对于更频繁地使用直接方法确实有很好的论据。

在这种情况下,需要更多的特异性来帮助编译器理解应该解析哪个实例。虽然任何情况下都Monoid可以有一个“计数和组合”Measured实例,但尚不清楚这是否是规范实例。由于类Measured要求Measured v a | a -> v我们必须选择v规范。

最可能的方法是创建一个newtype包装器

newtype Counted a = Counted a
instance Monoid a => Measured (Sum Int, a) (Counted a) where
  measure (Counted x) = (Sum 1, x)

这给了我们所需的规范性。在某些情况下,这可能Monoid直接传递函数字典更方便。

于 2013-08-10T17:05:12.587 回答