3

详细地说,通常可以为类型类实例函数提供默认实现,但我想知道是否也可以为其他类型类的类型类实例提供默认实现。

例如,假设我正在实现类型 classY并且我希望所有实例aY满足X a其他类型 class X。最初我试图通过写作来做到这一点instance Y a => X a where ...,但看到这实际上是不可能的(Haskell Constraint 不小于实例头)。但是,与另一个问题中描述的可能有多个类型类约束的更一般情况不同,我的情况下只有一个类约束,所以我认为可能有一种方法可以在课堂上做到这一点定义级别,可能使用 Haskell 语言扩展。

另一个问题中描述的方法似乎不太顺利 - 假设X实际上是Ord. Ord由 some包装可防止在原始类型上newtype直接使用函数。Ord

4

2 回答 2

9

这里通常的技巧是newtype用你想要的实例定义一个包装器。请参阅WrappedMonoid此示例。在你的情况下:

newtype WrappedY a = WrapY { unwrapY :: a }

instance Y a => X (WrappedY a) where 
  -- your default implementation here

然后,具有实例的类型Y可以派生X使用新DerivingVia扩展的实例。

{-# LANGUAGE DerivingVia #-}

data SomeType = ...
  deriving X via WrappedY SomeType

instance Y SomeType where
  -- your implementation here
于 2019-01-27T21:04:20.487 回答
5

如果您的用户有可用的 GHC 8.6+(DerivingVia是一个相当新的扩展),Alec 的答案中的新类型包装器 + DerivingVia 建议效果很好。如果这不是一个选项,您可以执行以下操作 -

  1. 提供一个类似的方法,它提供了viaimplXViaY的方法实现。例如,这有时是用 Applicative 实例完成的,其形式是where是基于来自 Monad 的实现,或者是 Functor 的where是基于Applicative 的实现。这不需要扩展。XY(<*>) = apap>>=fmap = liftAliftA(<*>)

  2. 提供一个 Template Haskell 函数,在类型类有很多方法的情况下自动使用默认定义(这基本上是 1 的扩展)。所以makeXviaY ''MyType对于用户来说。这需要客户端启用 TemplateHaskell。

于 2019-01-27T21:15:50.350 回答