[Haskell] GADT and constraints [Was: Rebindable syntax for monads
and arrows]
Martin Sulzmann
sulzmann at comp.nus.edu.sg
Tue Jan 11 10:24:41 EST 2005
Hi,
> I can't understand how constraints float at all. In the following code:
>
Ex1:
> > class Foo1 a where foo1 :: a -> String
> > class Foo2 a where foo2 :: a -> String
> >
> > instance Foo1 Bool where foo1 _ = "Bool"
> > instance Foo2 Char where foo2 _ = "Char"
> >
> > data U a where
> > Ub :: a -> U a
> > Uc :: a -> U a
> >
> > foo (Ub a) = foo1 a
> > foo (Uc a) = foo2 a
>
> What is the type of foo? GHC snapshot 6.3.20041106 happily accepts
> that code, and even infers
> *M> :t foo
> foo :: forall a. (Foo2 a, Foo1 a) => U a -> String
>
> but that seems odd. In any value of type U a, either Ub alternative is
> present, or Uc. They can never be both. Then why do we get the
> constraint that is the intersection of the two constraints rather than
> the union of them?
Inference is conservative and combines (ie. intersects) the results
from both branches. The type is correct (Chameleon infers the same type).
Take a look at
A Unifying Inference Framework for Hindley/Milner with Extensions
(http://www.comp.nus.edu.sg/~sulzmann/)
for a detailed description of inference.
> BTW, when I tried to do
>
Ex2:
> > data U a where
> > Ub :: Foo1 => a -> U a
> > Uc :: Foo2 => a -> U a
>
>
Replace Foo1 by Foo1 a and Foo2 by Foo2 a.
then foo has type U a -> String
> Anyway, even though GHC accepts the code and infers the type for foo,
> the function is unusable. An attempt to evaluate 'foo (Ub True)' ends
> up in an error message that there is no instance of Foo2 Bool. Indeed,
> there isn't. But why that should matter if I'm only interested in the
> Ub alternative? Again, the function 'foo' seems legitimate, and can be
> easily expressed either in Martin Sulzmann's interpretation of GRDT
> via existentials, or using the typeclass representation of GADT. For
> example:
>
> > data Ub a = Ub a
> > data Uc a = Uc a
> >
> > class Foo t where foo:: t -> String
> >
> > instance Foo1 a => Foo (Ub a) where
> > foo (Ub a) = foo1 a
> > instance Foo2 a => Foo (Uc a) where
> > foo (Uc a) = foo2 a
>
> Here, the constraint Foo is clearly the `union' of Foo1 and Foo2 (the
> discriminated union at that).
>
You're encoding Ex2 and not Ex1. Ex2 uses GADTs (aka GRDTs, ...)
but Ex1 only uses ordinary algebraic data types.
Martin
More information about the Haskell
mailing list