Thanks Cédric for your explanations. To sum up, that's the way I understood all this, in a bit less formal way: (Could help some, I guess)
Universal quantification (forall) means that the *caller *will instanciate ("fix") the type variables, and that *callee *cannot know those types. Existential quantification (through data E = forall a. E a) means that the *callee *will fix the type variables, and that the *caller *cannot know those types. Now concerning the way existential (resp. universal) in a context becomes universal (resp. existential) in the outer context: f :: forall a. a -> a means that when you're *inside *f, 'a' will have been fixed to some type *that f cannot know*, only the outer context can. f says "I can work with any type a, so give me whatever type you want". g :: (forall a. a -> a) -> Something g f = .... means the exact opposite: 'a' is universally quantified in the signature of 'f', so it is existentially quantified in that of 'g'. So it's equivalent to: g :: exists a. (a -> a) -> Something g says "I can only work with *some* specific types 'a', but as you don't know what they will be, you can but give me something that can will work with *any *type 'a'." And so on: h :: ((forall a. a -> a) -> Something) -> SomethingElse h g = ... h can also be written as follows, am I right?: h :: forall a. ((a -> a) -> Something) -> SomethingElse And to be sure: foo :: forall a. a -> (forall b. b -> a) is equivalent to: foo :: forall a b. a -> b -> a Right? And: foo :: forall a. a -> ((forall b. b) -> a) to: foo :: forall a. exists b. a -> b -> a ?? 2012/1/4 AUGER Cédric <sedri...@gmail.com> > Le Wed, 4 Jan 2012 20:13:34 +0100, > Yves Parès <limestr...@gmail.com> a écrit : > > > > f :: forall a. (forall b. b -> b) -> a -> a > > > f id x = id x > > > > > is very similar to the first case, x is still universally > > > quantified (a) and there is an existential quantification in id (b). > > > > I don't get it. What is 'id' existentially quantified in? > > f calls id so f will decide what will be its type. In this case, > > because it's applied to 'x', id type will get instanciated to 'a -> > > a' (where a is rigid, because bound by f signature). > > Sorry I badly expressed it. > > I wanted to say that the "b" type variable in "id" is existentially > quantified in the type of f. > > forall a. (forall b. b -> b) -> a -> a > ^ > existentially quantified in the overall type > but locally universally quantified in the type forall b. b -> b > > It is the same things for data types. > > Consider the data type of lists: > > data List a = Nil > | Cons a (List a) > > its elimination principle is: > > list_rec :: forall a b. b -> (a -> list a -> b -> b) -> List a -> b > list_rec acc f l = case l of > Nil -> acc > Cons a l -> f a l (list_rec acc f l) > (it is the type version of the induction principle: > "∀ P. P Nil ⇒ (∀ x l, P l ⇒ P (Cons x l)) ⇒ ∀ l, P l" > which by Curry-DeBruijn-Horward gives > b -> ( b -> List a -> b -> b ) -> list a -> b > you can also find an "optimized" version where "l" is removed from > the recursion as its information can be stored in "P l/b"; > this function is exactly "foldr" > ) > > Now if we take a look at the elimination principle, > > forall a b. b -> (a -> list a -> b -> b) -> List a -> b > > contains only universally quantified variables. > > Cons as a function is also universally quantified: > Cons :: forall a. a -> List a -> List a > > Nil as a function is also universally quantified: > Nil :: forall a. List a > > So that elimination and introduction are all universally quantified. > (Nothing very surprising here!) > ===================================================================== > > Now for the existential part: > > data Existential = forall b. ExistIntro b > > What is its elimination principle (ie. what primitive function allows > us to use it for all general purpouses)? > > Existential types are less easy to manipulate, since in fact they > require functions which takes universally quantified functions as > arguments. > > existential_elim :: forall b. (forall a. a -> b) -> Existential -> b > existential_elim f e = case e of > ExistIntro x -> f x > (∀ P. (∀ a. a ⇒ P (ExistIntro a)) ⇒ ∀ e. P e) > > Here, you can see that "a" is existentially quantified (isn't it > normal for a type containing existentials)! > > Note also that its introduction rule: > ExistIntro :: forall a. a -> Existential > is also universally quantified (but with a type variable which doesn't > appear in the introduced type). > > Which is not to mess with: > > data Universal = UnivIntro (forall a. a) > > elimination principle: > univ_elim :: forall b. ((forall a. a) -> b) -> Universal -> b > univ_elim f u = case u of > UnivIntro poly -> f poly > (∀ P. (∀ (poly:∀a.a). P (UnivIntro poly)) ⇒ ∀ u. P u) > > Here you can see that you don't need special syntax, and again, the > elimination principle is universally quantified in both a and b. > Its introduction has some existential quantification (which doesn't > appear in the introduced type). > > > > > 2012/1/4 AUGER Cédric <sedri...@gmail.com> > > > > > Le Wed, 4 Jan 2012 14:41:21 +0100, > > > Yves Parès <limestr...@gmail.com> a écrit : > > > > > > > > I expected the type of 'x' to be universally quantified, and > > > > > thus can be unified with 'forall a. a' with no problem > > > > > > > > As I get it. 'x' is not universally quantified. f is. [1] > > > > x would be universally quantified if the type of f was : > > > > > > > > f :: (forall a. a) -> (forall a. a) > > > > > > > > [1] Yet here I'm not sure this sentence is correct. Some heads-up > > > > from a type expert would be good. > > > > > > > > > > For the type terminology (for Haskell), > > > > > > notations: > > > a Q∀ t := a universally quantified in t > > > a Q∃ t := a existentially quantified in t > > > a Q∀∃ t := a universally (resp. existentially) quantified in t > > > a Q∃∀ t := a existentially (resp. universally) quantified in t > > > > > > Two different names are expected to denote two different type > > > variables. A type variable is not expected to be many times > > > quantified (else, it would be meaningless, a way to omit this > > > hypothesis is to think of path to quantification instead of > > > variable name; to clarify what I mean, consider the following > > > expression: > > > > > > forall a. (forall a. a) -> a > > > > > > we cannot tell what "a is existentially quantified" means, since we > > > have two a's; but if we rename them into > > > > > > forall a. (forall b. b) -> a > > > or > > > forall b. (forall a. a) -> b > > > > > > , the meaning is clear; in the following, I expect to always be in a > > > place where it is clear.) > > > > > > rules: > > > (1) ⊤ ⇒ a Q∀ forall a. t > > > (2)b Q∀∃ t ⇒ b Q∀∃ forall a. t > > > (3)a Q∀∃ u ⇒ a Q∀∃ t -> u (in fact it is the same rule as above, > > > since "->" is an non binding forall in > > > type theory) > > > (4)a Q∀∃ t ⇒ a Q∃∀ t -> u > > > > > > So in this context, we cannot say that 'x' is universally or > > > existentially quantified, but that the 'type of x' is universally or > > > existentially quantified 'in' some type (assuming that the type of x > > > is a type variable). > > > > > > so: > > > > > > a Q∃ (forall a. a -> a) -> forall b. b -> b > > > since (4) and "a Q∀ forall a. a -> a" due to (1) > > > > > > and > > > > > > b Q∀ (forall a. a -> a) -> forall b. b -> b > > > since (3) and "b Q∀ forall b. b -> b" due to (1) > > > > > > The quick way to tell is count the number of unmatched opening > > > parenthesis before the quantifying forall (assuming you don't put > > > needless parenthesis) if it is even, you are universally > > > quantified, if it is odd, you are existentially quantified. > > > > > > So in: > > > > > > f :: (forall a. a -> a) -> forall b. b -> b > > > f id x = id x > > > > > > the type of 'x' (b) is universally quantified in the type of f, > > > and the type of 'id' contains an existential quantification in the > > > type of f (a). > > > > > > In: > > > > > > f :: forall a. (a -> a) -> a -> a > > > f id x = id x > > > > > > the type of 'x' (a) is universally quantified in the type of f; > > > there is no existential quantification. > > > > > > f :: forall a. (forall b. b -> b) -> a -> a > > > f id x = id x > > > > > > is very similar to the first case, x is still universally > > > quantified (a) and there is an existential quantification in id (b). > > > > > > I guess that the only difference is that when you do a > > > "f id" in the last case, you might get an error as the program > > > needs to know the "a" type before applying "id" (of course if there > > > is some use later in the same function, then the type can be > > > inferred) > > > > > > Hope that I didn't write wrong things, and if so that you can tell > > > now for sure if a type is universally or existentially quantified. > > > > >
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe