我有以下代码(转换类似于转换)
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
,OVERLAPS
和OVERLAPPING
的不同组合,但没有任何效果。我怎么解决这个问题?
答案 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中给出。