Coercible class (Was: newtype wrappers)
Simon Peyton-Jones
simonpj at microsoft.com
Mon Sep 16 05:53:23 UTC 2013
Richard raises a question about coherence below. (Coherence, not soundness.)
But it's a coherence problem we already have. Given his Foo type,
| > data Foo a where -- a's role is representational; this is NOT a GADT
| > MkFoo :: Ord a => a -> Foo a
suppose we define
bar :: Foo T -> Bool
bar (MkFoo x) = x>x
At the use of (>) we have potentially two instances of (Ord T) available
- one bound by the MkFoo constructor
- one top-level instance
and we could easily have more; et
bar2 :: Foo T -> Foo T -> Bool
bar2 (MkFoo x) (MkFoo y) = x>y
These instances could potentially have different implementations if the (Foo T) values were constructed in different modules, each with its own (instance Ord T).
So this isn't really a new problem, and it's one that doesn't seem too bad in practice.
Simon
| A question about the existing check: How does it treat constraints? For example,
| say we have
|
| > data Foo a where -- a's role is representational; this is NOT a GADT
| > MkFoo :: Ord a => a -> Foo a
| >
| > newtype Age = MkAge Int deriving Eq -- the Eq is to satisfy Ord's superclass
| constraint
| > instance Ord Age where
| > (MkAge a) `compare` (MkAge b) = b `compare` a -- args are reversed
| >
| > fooInt :: Foo Int
| > fooInt = MkFoo 5
| >
| > fooAge :: Foo Age
| > fooAge = coerce fooInt -- it seems this would be accepted
| >
| > confused :: Foo Age -> Ordering
| > confused (MkFoo x) = x `compare` (MkAge 0)
|
| What will confused do? It has potentially two, conflicting instances for Ord to
| hand: one in the global context; and one from pattern-matching MkFoo, which was
| creating by coercing from Ord Int. I have a hard time seeing the solution to be
| IncoherentInstances, because it's not clear which chunk of code would trigger the
| need for that extension.
|
| Also, it's possible for there to be "abstract" classes, which don't export all of their
| methods or use other tricks to prevent instances (non-exported superclasses, for
| example) outside of the library. Are these checked for?
|
| Actually, come to think of it, the example I have above doesn't really interact with
| the Safe Haskell check -- it's a problem regardless, unless I'm confused.
More information about the ghc-devs
mailing list