Reputation: 3737
I get error:
Duplicate instance declarations:
instance [overlap ok] EnumTag a => Read a
-- Defined at /XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/intero/intero2932Xpa-TEMP.hs:110:27
instance [overlap ok] StrTag a => Read a
-- Defined at /XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/intero/intero2932Xpa-TEMP.hs:121:27 (intero)
For this code:
class (Show a, Enum a) => EnumTag a where
anyEnum :: a
instance {-# OVERLAPS #-} EnumTag a => Read a where
readPrec = RP.lift P.skipSpaces >> expectEnum
instance {-# OVERLAPS #-} EnumTag a => Eq a where
a == b | a == anyEnum || b == anyEnum = True
| otherwise = fromEnum a == fromEnum b
class StrTag a where
anyStr :: a
tagPrefix :: a -> String -- ^ should be constant
toStr :: String -> a
instance {-# OVERLAPS #-} StrTag a => Read a where
readPrec = parens $ do
RP.lift P.skipSpaces
(RP.lift $ expectShown anyStr) <++ RP.lift g
where g = do
Just s@(_:_) <- L.stripPrefix tagPrefix <$> expectTag
return $ toStr s
Why does it happen? Read a
in 1st instance is valid only when a
is EnumTag
, in 2nd one - is valid only when a
is StrTag
.
How can I fix this error and to create "default" instances for EnumTag
and to StrTag
, so client code will "inherit" those functionality (Read) simple, only with instantiation of EnumTag
or StrTag
?
Upvotes: 0
Views: 248
Reputation: 116139
Overlapping instances are quite fragile. Arguably, they should never be used.
Anyway, overlapping instances cause GHC to avoid committing to an instance too soon. E.g.
-- overlapping
instance ... => Read [Int] -- 1
instance ... => Read [a] -- 2
When GHC has to solve a constraint such as Read [b]
, it does not commit to instance 2, since it can't rule out the more specific instance 1: after all the type variable b
could be later on found to be Int
.
If later on, b
is found to be Int
, instance 1 will be picked. If b
is instead found to be String
, GHC will pick instance 2.
This however requires that there is a "best choice" in each case. I.e. when b = Int
, both instances could be used, but 1 is more specific, hence it is the "best", and GHC chooses that.
In the case you have instances
instance ... => Read [a] -- 3
instance ... => Read [a] -- 4
then no best instance exists, since they use the same head Read [a]
, making the choice to be inherently ambiguous, and GHC rejects that.
What probably confuses you is that GHC will never consider what's on the left of =>
(the "context") to pick an instance. It does not matter if the instances will not overlap once you consider their context, since no type can satisfy both contexts of 3 and 4. Detecting that the contexts are mutually exclusive is very hard in general, and GHC does not even attempt to do so. Only the instance head (on the right of =>
) is considered.
There is no way to create such two default instances which are turned on automatically unless the client defines a more specific one.
I'd prefer to avoid overlaps in instances, and provide a default implementation outside an instance. E.g.
-- library
readPrec_fromStrTag :: StrTag a => Int -> ReadS a
readPrec_fromStrTag = parens $ do
RP.lift P.skipSpaces
(RP.lift $ expectShown anyStr) <++ RP.lift g
where g = do
Just s@(_:_) <- L.stripPrefix tagPrefix <$> expectTag
return $ toStr s
If the client wants to use that, they can enable the default implementation using
instance StrTag T where
...
instance Read T where
readPrec = readPrec_fromStrTag -- use default from the library
If this and other boilerplate is becoming too much burdensome, Template Haskell might help the user in writing that.
Upvotes: 4