#1470: Overlapping (etc) instances
--------------------------------------+-------------------------------------
Reporter: igloo | Owner: simonpj
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler (Type checker) | Version: 6.6.1
Severity: normal | Keywords:
Difficulty: Unknown | Os: Unknown
Testcase: | Architecture: Unknown
--------------------------------------+-------------------------------------
This self-contained module:
{{{
{-# LANGUAGE FlexibleInstances, OverlappingInstances, UndecidableInstances
#-}
module Foo where
class Sat a
class Data ctx a
instance Sat (ctx Char) => Data ctx Char
instance (Sat (ctx [a]), Data ctx a) => Data ctx [a]
class Data FooD a => Foo a
data FooD a = FooD
instance Foo t => Sat (FooD t)
instance Data FooD a => Foo a
instance Foo a => Foo [a]
instance Foo [Char]
}}}
gives this error in the HEAD (and a similar, but less helpful, error in
6.6):
{{{
$ ghc -c Foo.hs
Foo.hs:18:0:
Overlapping instances for Foo [a]
arising from the superclasses of an instance declaration
at Foo.hs:18:0
Matching instances:
instance [overlap ok] (Foo a) => Foo [a]
-- Defined at Foo.hs:18:0-30
instance [overlap ok] Foo [Char] -- Defined at Foo.hs:19:0-33
(The choice depends on the instantiation of `a'
Use -fallow-incoherent-instances to use the first choice above)
In the instance declaration for `Foo [a]'
}}}
Simon writes:
{{{
The reason is this:
In the instance for Foo [a]
we need a superclass (Data FooD [a])
using the instance for Data, we therefore need
(Sat (FooD [a], Data FooD a)
But we are given Foo a, and hence its superclass Data FooD a
So that leaves (Sat (FooD [a]))
Using the instance for Sat means
we need (Foo [a])
At that point GHC says there are two instances that match Foo [a], and
which one
to choose depends on how you instantiate a.
What we wanted was to "tie the knot" and use Foo [a] recursively, the very
one
we are constructing. GHC does that when solving Foo [a], but not when
constructing it.
This is a good point, I will think about it. It's a bit delicate.
Meanwhile,
can you Trac it? It's a nice example.
}}}
A larger module showing how the instances above can be desirable in a real
program is this (requires the syb-with-class package from hackage):
{{{
{-# LANGUAGE TemplateHaskell, FlexibleInstances, CPP,
OverlappingInstances, UndecidableInstances #-}
module Main where
import Data.Generics.SYB.WithClass.Basics
import Data.Generics.SYB.WithClass.Instances ()
data Element = Elem String [Element]
| CData String
deriving Show
class Data XmlD a => Xml a where
toXml :: a -> [Element]
toXml = defaultToXml
data XmlD a = XmlD { toXmlD :: a -> [Element] }
xmlProxy :: Proxy XmlD
xmlProxy = error "xmlProxy"
instance Xml t => Sat (XmlD t) where
dict = XmlD { toXmlD = toXml }
defaultToXml :: Xml t => t -> [Element]
defaultToXml x = [Elem (constring $ toConstr xmlProxy x)
(concat $ gmapQ xmlProxy (toXmlD dict) x)]
-----
instance Data XmlD t => Xml t
#ifdef STRING
instance Xml String where
toXml x = [Elem "string" [CData x]]
#endif
#ifdef LIST
instance Xml a => Xml [a] where
toXml = concatMap toXml
#endif
main :: IO ()
main = do print $ toXml (Just True)
print $ toXml [True, False]
print $ toXml "foo"
}}}
which allows us to specialise XML marshalling for either lists (ignoring
all the (:) and [] constructors) or strings (turn them into CData), but
not both:
{{{
$ ghci -v0 -DLIST z.hs
*Main> main
[Elem "Just" [Elem "True" []]]
[Elem "True" [],Elem "False" []]
[Elem "f" [],Elem "o" [],Elem "o" []]
*Main>
$ ghci -v0 -DSTRING z.hs
*Main> main
[Elem "Just" [Elem "True" []]]
[Elem "(:)" [Elem "True" [],Elem "(:)" [Elem "False" [],Elem "[]" []]]]
[Elem "string" [CData "foo"]]
*Main>
$ ghci -v0 -DLIST -DSTRING z.hs
[overlapping instances error]
}}}
If we replace the
{{{
instance Xml a => Xml [a] where
}}}
line with
{{{
instance (Xml a, Xml [a]) => Xml [a] where
}}}
then everything seems to work out, but this feels a little dodgy.
--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/1470>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs