为什么有一个类型类测量Data.FingerTree而不仅仅是一个函数?

时间:2013-08-10 07:15:37

标签: haskell

我不明白为什么使用类型类FingerTree实现Measured

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

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

当然,由于FingerTree本身是Measured,因此我们无法获得类型类重叠。

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

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

1 个答案:

答案 0 :(得分: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函数字典更方便。