如何解决重叠实例

时间:2016-04-28 11:55:49

标签: haskell

我有以下代码(转换类似于转换)

instance {-# OVERLAPS #-} Transformable a a where
  transform x = x

instance {-# OVERLAPPABLE #-} (Transformable l l',   Transformable r r' )
         => Transformable (Either l r) (Either l' r')
  where
    transform = bimap transform transform

当然,在我尝试将Either a b转换为Either a b并获取以下错误消息的情况下,这些实例会重叠(ParsingError是{{1}的类型别名}})

Either something somethingElse

我尝试了 Overlapping instances for Transformable (parsingerror text) (parsingerror text) arising from a use of ‘makereceipt’ matching instances: Matching instances: Overlapping instances for Transformable (ParsingError Text) (ParsingError Text) arising from a use of ‘makeReceipt’ Matching instances: instance [overlappable] (Transformable l l', Transformable r r') => Transformable (Either l r) (Either l' r') instance [overlappable] (Transformable l l', Transformable r r') => Transformable (Either l r) (Either l' r') -- Defined at Handler/GLEnterReceiptSheet/ReceiptRow.hs:154:31 instance [overlap ok] Transformable a a -- Defined at Handler/GLEnterReceiptSheet/ReceiptRow.hs:151:27 OVERLAPSOVERLAPPING的不同组合,但没有任何效果。我怎么解决这个问题?

1 个答案:

答案 0 :(得分:9)

您必须更改其中一个实例定义:

class Transformable a b where 
  transform :: a -> b 

-- this one
instance {-# OVERLAPS #-} (a ~ b) => Transformable a b where
  transform x = x

instance (Transformable l l', Transformable r r' )
       => Transformable (Either l r) (Either l' r') where
  transform = either (Left . transform) (Right . transform) 

test0 :: (Transformable a a', Transformable b b') => Either a b -> Either a' b'
test0 = transform

无论您在另一个实例上使用哪种重叠,代码都将正常工作。你实际上并不需要在第二个实例上使用任何编译指示。

原始代码的问题是实例实际上是不连贯,而不仅仅是重叠,因此{-# OVERLAPS/OVERLAPPING/OVERLAPPABLE #-}的任何组合都不能保存您 - 您需要使用{{1} },这是不可取的,我不会推荐。 GHC将在错误消息中告诉您这种不一致性:

{-# INHCOHERENT #-}

基本上,为了从重叠的实例中挑选,一个实例必须是"最具体的"对于您要匹配的类型。详细信息在user guide中给出。