<HTML dir=ltr><HEAD><TITLE>Re: [Haskell-cafe] type questions again....</TITLE>
<META http-equiv=Content-Type content="text/html; charset=unicode">
<META content="MSHTML 6.00.6000.16587" name=GENERATOR></HEAD>
<BODY>
<DIV id=idOWAReplyText91147 dir=ltr>
<DIV dir=ltr><FONT face=Arial color=#000000 size=2>Is my problem here, simply that the forall extension in GHC is misleading.....that the "forall" in</FONT></DIV>
<DIV dir=ltr><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV dir=ltr>"MkSwizzle :: (forall a. Ord a =&gt; [a] -&gt; [a]) -&gt; Swizzle"</DIV>
<DIV dir=ltr>&nbsp;</DIV>
<DIV dir=ltr>is not the same beast as the "forall" in..</DIV>
<DIV dir=ltr>&nbsp;</DIV>
<DIV dir=ltr>data Accum a = forall s. MkAccum s (a -&gt; s -&gt; s) (s -&gt; a)<BR></DIV>
<DIV dir=ltr>really</DIV>
<DIV dir=ltr>&nbsp;</DIV>
<DIV dir=ltr>data Accum a = exists s. MkAccum s (a -&gt; s -&gt; s) (s -&gt; a)<BR></DIV>
<DIV dir=ltr>would be much better syntax....</DIV>
<DIV dir=ltr>&nbsp;</DIV>
<DIV dir=ltr>don't get me wrong....I still don't especially understand...but if it's a misleading label...I can mentally substitute "exists" whenever I see a "forall" without a "=&gt;".<BR>
<HR tabIndex=-1>
<FONT face=Tahoma size=2><B>From:</B> Luke Palmer [mailto:lrpalmer@gmail.com]<BR><B>Sent:</B> Fri 11/01/2008 18:03<BR><B>To:</B> Nicholls, Mark<BR><B>Cc:</B> haskell-cafe@haskell.org<BR><B>Subject:</B> Re: [Haskell-cafe] type questions again....<BR></FONT><BR></DIV></DIV>
<DIV>
<P><FONT size=2>On Jan 11, 2008 5:47 PM, Nicholls, Mark &lt;Nicholls.Mark@mtvne.com&gt; wrote:<BR>&gt; &gt; If you wrap an existential type up in a constructor, not<BR>&gt; &gt; much changes:<BR>&gt;<BR>&gt; If you wrap a what?....should this read existential or universal?<BR><BR>Whoops, right, universal.<BR><BR>&gt; &gt; &gt; newtype ID = ID (forall a. a -&gt; a)<BR>&gt; &gt;<BR>&gt; &gt; ID can hold any value of type forall a. a -&gt; a; i.e. it can hold any<BR>&gt; &gt; value which exhibits the property that it can give me a value of type<BR>&gt; &gt; a -&gt; a for any type a I choose.&nbsp; In this case the only things ID can<BR>&gt; &gt; hold are id and _|_, because id is the only function that has that<BR>&gt; &gt; type.&nbsp;&nbsp; Here's how I might use it:<BR>&gt;<BR>&gt; It's the only function you've defined the type of....<BR>&gt;<BR>&gt; Id2 :: forall a. a -&gt; a<BR>&gt;<BR>&gt; Now it can hold id2?<BR><BR>Well, that's not what I meant, but yes it can hold id2.<BR><BR>What I meant was that, in this case, id2 = _|_ or id2 = id, there are no<BR>other possibilities.<BR><BR><BR>&gt; &gt; &gt; id' :: forall a. Num a =&gt; a -&gt; a<BR>&gt; &gt; &gt; id' = id&nbsp; -- it doesn't have to use the constraint if it doesn't<BR>&gt; want to<BR>&gt;<BR>&gt; "it doesn't have to use the constraint if it doesn't want to" ?<BR>&gt;<BR>&gt; If id was of type..<BR>&gt;<BR>&gt; Id::forall a. Ord a =&gt; a -&gt; a<BR>&gt;<BR>&gt; Then I assume it would complain?<BR><BR>Yes.<BR><BR>&gt; &gt; but you need to use constructors to use<BR>&gt; &gt; them.&nbsp; I'll write them using GADTs, because I think they're a lot<BR>&gt; &gt; clearer that way:<BR>&gt; &gt;<BR>&gt; &gt; data NUM' where<BR>&gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp; NUM' :: Num a =&gt; a -&gt; NUM'<BR>&gt; &gt;<BR>&gt; &gt; Look at the type of the constructor NUM'.&nbsp; It has a universal type,<BR>&gt; &gt; meaning whatever type a you pick (as long as it is a Num), you can<BR>&gt; &gt; create a NUM' value with it.<BR>&gt;<BR>&gt; yes<BR>&gt;<BR>&gt; and then it goes wrong...<BR>&gt;<BR>&gt; &gt; So the type contained inside the NUM'<BR>&gt; &gt; constructor<BR>&gt;<BR>&gt; ?<BR>&gt;<BR>&gt; &gt; is called existential (note that NUM' itself is just a<BR>&gt; &gt; regular ADT; NUM' is not existential).<BR>&gt; &gt;<BR>&gt;<BR>&gt; Why existential....see below...I have a guess<BR><BR>Okay, I was being handwavy here.&nbsp; Explaining this will allow me to<BR>clear this up.<BR><BR>If you take the non-GADT usage of an existential type:<BR><BR>data Foo<BR>&nbsp;&nbsp;&nbsp; = forall a. Num a =&gt; Foo a<BR><BR>That is isomorphic to a type:<BR><BR>data Foo<BR>&nbsp;&nbsp;&nbsp; = Foo (exists a. Num a =&gt; a)<BR><BR>Except GHC doesn't support a keyword 'exists', and if it did, it would only be<BR>able to be used inside constructors like this (in order for inference<BR>to be decidable),<BR>so why bother?&nbsp; That's what I meant by "the type inside the constructor", Foo is<BR>not existential, (exists a. Num a =&gt; a) is.<BR><BR>&gt; &gt; So when you have:<BR>&gt; &gt;<BR>&gt; &gt; &gt; negNUM' :: NUM' -&gt; NUM'<BR>&gt; &gt; &gt; negNUM' (NUM' n) = NUM' (negate n)<BR><BR>Here n has an existential type, specifically (exists a. Num a =&gt; a).<BR><BR>&gt; &gt; Here the argument could have been constructed using any numeric type<BR>&gt; &gt; n, so we know very little about it.&nbsp; The only thing we know is that it<BR>&gt; &gt; is of some type a, and that type has a Num instance.<BR>&gt;<BR>&gt; I think one of the harrowing things about Haskell is the practice of<BR>&gt; overloading data constructors with type names....it confuses the hell<BR>&gt; out of me....<BR><BR>Yeah that took a little getting used to for me too.&nbsp; But how am I supposed<BR>to come up with enough names if I want to name them differently!?&nbsp; That<BR>would require too much creativity...&nbsp; :-)<BR><BR>&gt; OK so this declaration says that forall x constructed using "NUM'<BR>&gt; n"...there *exists* a type T s.t. T is a member of type class NUM"...<BR><BR>(you probably meant type class Num here)<BR><BR>&gt; which in term implies that that there exists the function negate...<BR>&gt;<BR>&gt; yes?<BR><BR>Huh, I had never thought of it like that, but yes.<BR><BR>I just realized that I think of programming in a way quite different<BR>than I think of logic.&nbsp; Maybe I should try to have my brain unify them.<BR><BR>&gt; &gt; &gt; doubleNUM' :: NUM' -&gt; NUM'<BR>&gt; &gt; &gt; doubleNUM' (NUM' n) = NUleM' (n + n)<BR>&gt; &gt;<BR>&gt; &gt; We can add it to itself, but note:<BR>&gt; &gt;<BR>&gt; &gt; &gt; addNUM' :: NUM' -&gt; NUM' -&gt; NUM'<BR>&gt; &gt; &gt; addNUM' (NUM' a) (NUM' b) = NUM (a + b)&nbsp; -- Illegal!<BR>&gt; &gt;<BR>&gt; &gt; We can't add them to each other, because the first argument could have<BR>&gt; &gt; been constructed with, say, a Double and the other with a Rational.<BR>&gt; &gt;<BR>&gt; &gt; But do you see why we're allowed to add it to itself?<BR>&gt;<BR>&gt; We can add it to itself because "+" is of type "a-&gt;a-&gt;a"...<BR><BR>Yep, so whatever type a n happens to have, it matches both arguments.<BR><BR>&gt; &gt; How about this:<BR>&gt; &gt;<BR>&gt; &gt; &gt; data Variant where<BR>&gt; &gt; &gt;&nbsp;&nbsp;&nbsp; Variant :: a -&gt; Variant<BR>&gt; &gt;<BR>&gt; &gt; This is a type that can be constructed with any value whatsoever.<BR>&gt; &gt; Looks pretty powerful... but it isn't.&nbsp; Why not?<BR>&gt; &gt;<BR>&gt;<BR>&gt; Eeek.....<BR>&gt;<BR>&gt; Because a could be of any type whatsover?...so how I actually do<BR>&gt; anything with it?<BR><BR>Right.<BR><BR>Luke<BR></FONT></P></DIV></BODY></HTML>