Hi John,
Dimitrios, Simon and I have been talking about FirstClassExistentials
recently. (Since they aren't currently implemented in any Haskell
compiler, their inclusion in Haskell' seems unlikely, but I would like
to seem them discussed for not-too future versions of Haskell.)
In particular, they do seem like a natural extension to arbitrary-rank
polymorphism and I agree that they have the potential to be much more
convenient than ExistentialQuantification, particularly in conjunction
with GADTs and ImpredicativePolymorphism. I don't think it makes sense
to add them without some sort of arbitrary-rank polymorphism (as
discussed in the paper "Practical type inference for arbitrary-rank
types") because they need to be enabled by typing annotations (and
perhaps some kind of local inference) as is necessary for arbitrary-rank
universals. Like first-class universals, types containing first-class
existentials cannot be guessed, so if a function should return something
of type exists a. Show a => a, then the type of the function should be
annotated.
The tricky parts that Dimitrios, Simon and I are talking about now have
to do with the subsumption relation: when is one type "more general"
than another, given that both may contain arbitrary universal and
existential types. This subsumption relation is important for
automatically coercing into and out of the existential type.
For example, if
f :: (exists a. (a, a -> a)) -> Int
then it should be sound to apply f to the argument
(3, \x -> x + 1)
just like it is sound to apply
g :: forall a. (a, a->a) -> Int
to the same argument.
You are right in that "strictly contravariant" existentials (to coin a
new term) don't add much to expressiveness, and perhaps that observation
will help in the development of our subsumption relation. (As an aside,
I think that this is analogous to the fact that "strictly covariant"
first-class universals aren't all that important.
f :: Int -> (forall a. a -> a)
should be just as good as
f :: forall a. Int -> a -> a.
Some arbitrary rank papers disallow types like the former: in the
practical type inference paper, we just make sure that these two types
are equivalent. )
--Stephanie
John Meacham wrote:
On Tue, Feb 14, 2006 at 11:56:25PM +0000, Ross Paterson wrote:
Is this the same as ExistentialQuantification?
(And what would an existential in a covariant position look like?)
well, the ExistentialQuantification page is restricted to declaring data types
as having existential components. in my opinion that page name is
something of a misnomer. by ExistentialQuantifiers I mean being able
to use 'exists <vars> . <type>' as a first class type anywhere you can
use a type.
data Foo = Foo (exists a . a)
type Any = exists a . a
by the page I mainly meant the syntatic use of being able to use
'exists'. Depending on where your type system actually typechecks it as
proper, it implys other extensions.
if you allow them as the components of data structures, then that is
what the current ExistentialQuantification page is about, and all
haskell compilers support this though with differing syntax as described
on that page.
when existential types are allowed in covarient positions you have
'FirstClassExistentials' meaning you can pass them around just like
normal values, which is a signifigantly harder extension than either of
the other two. It is also equivalent to dropping the restriction that
existential types cannot 'escape' mentioned in the ghc manual on
existential types.
an example might be
returnSomeFoo :: Int -> Char -> exists a . Foo a => a
which means that returnsSomeFoo will return some object, we don't know
what, except that is a member of Foo. so we can use all of Foos class
methods on it, but know nothing else about it. This is very similar to
OO style programing.
when in contravarient position:
takesSomeFoo :: Int -> (exists a . Foo a => a) -> Char
then this can be simply desugared to
takesSomeFoo :: forall a . Foo a => Int -> a -> Char
so it is a signifgantly simpler thing to do.
A plausable desugaring of FirstClassExistentials would be to have them
turn into an unboxed tuple of the value and its assosiated dictionary
and type. but there are a few subtleties in defining the translation as
straight haskell -> haskell (we need unboxed tuples for one :)) but the
translation to something like system F is more straightforward.
there is also room for other extensions between the two which I am
trying to explore with jhc. full first class existentials are somewhat
tricky, but the OO style programming is something many people have
expressed interest in so perhaps there is room for something interesting
in the middle that satiates the need for OO programming but isn't as
tricky as full first class existentials. I will certainly report back
here if I find anything...
Also, someone in the know should verify my theory and terminology :)
John
_______________________________________________
Haskell-prime mailing list
Haskell-prime@haskell.org
http://haskell.org/mailman/listinfo/haskell-prime