<div class="gmail_quote">On Tue, Jan 20, 2009 at 1:14 PM, David Menendez <span dir="ltr">&lt;<a href="mailto:dave@zednenem.com">dave@zednenem.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div class="Ih2E3d">On Tue, Jan 20, 2009 at 2:51 PM, Mauricio &lt;<a href="mailto:briqueabraque@yahoo.com">briqueabraque@yahoo.com</a>&gt; wrote:<br>
&gt;&gt;&gt; But how is this:<br>
&gt;&gt;&gt; data SomeNum = forall a. SN a<br>
&gt;&gt;&gt; different from:<br>
&gt;&gt;&gt; data SomeNum = SN (forall a. a)<br>
&gt;<br>
&gt;&gt; At a glance they look the same to me — but only the first is accepted by<br>
&gt;&gt; ghc.<br>
&gt;<br>
&gt; Following the link you pointed in the last<br>
&gt; message, I found this at <a href="http://8.8.4.1" target="_blank">8.8.4.1</a>:<br>
&gt;<br>
&gt; data T a = T1 (forall b. b -&gt; b -&gt; b) a</div></blockquote><div><br></div><div>The constructor here is irrelevant. &nbsp;The function here can do anything a top-level function of type:</div><div><br></div><div>something :: b -&gt; b -&gt; b&nbsp;</div>
<div><br></div><div>I like to think about quantification in this regard in terms of isomorphisms. &nbsp;Think about what a function of type forall b. b -&gt; b -&gt; b can do. &nbsp;It cannot do anything with its arguments, because it must work on all types, so it only has one choice to make: it can return the first argument, or it can return the second argument.</div>
<div><br></div><div>So, forall b. b -&gt; b -&gt; b &nbsp;is isomorphic to Bool.</div><div><br></div><div>For symmetry, the constructor T1 has type:</div><div><br></div><div>T1 :: (forall b. b -&gt; b -&gt; b) -&gt; a -&gt; T1 a</div>
<div>&nbsp;</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div class="Ih2E3d"><br><br>
&gt; If I understand properly, it can be activated<br>
&gt; with -XPolymorphicComponents. It&#39;s different<br>
&gt; from my example, but I would like to know what<br>
&gt; it does that this can&#39;t:<br>
&gt;&nbsp;</div></blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div class="Ih2E3d">
&gt; data T a = forall b. T1 (b-&gt;b-&gt;b) a</div></blockquote><div><br></div><div>The constructor T1 here has type:</div><div><br></div><div>T1 :: forall b. (b -&gt; b -&gt; b) -&gt; a -&gt; T1 a</div><div><br></div><div>
See the difference?</div><div><br></div><div>You can pass the latter a function of any type you choose, eg. (Int -&gt; Int -&gt; Int) or ((Bool -&gt; Bool) -&gt; (Bool -&gt; Bool) -&gt; (Bool -&gt; Bool)). &nbsp;So when somebody gets a T from you, they have no idea what type the function you gave it was, so they can only use it in limited ways (in this case, nothing useful at all can be done with it).</div>
<div><br></div><div>Here&#39;s another existential type:</div><div><br></div><div>data T&#39; a = forall b. T&#39; (b -&gt; a) b</div><div>&nbsp;</div><div>Here, a T&#39; contains a value of some type b -- who knows what it is -- and a function to get from that value to an a. &nbsp;Since we don&#39;t know anything about b, all we can do is to apply the function.</div>
<div><br></div><div>T&#39; a is isomorphic to a. &nbsp;But it might have different operational behavior; e.g. maybe a is a huge list which is cheaply generated from some small generator value (of type b). &nbsp;Then if you pass a T&#39; around, it&#39;s the same as passing that big list around, except for you <span class="Apple-style-span" style="font-style: italic;">don&#39;t</span>&nbsp;cache the results of the list, improving memory performance. &nbsp;It&#39;s like inverse memoization.</div>
<div><br></div><div>Not all existential types are for inverse memoization, this is just one case.</div><div><br></div><div>I found it easiest to reason about these with the types of the constructors, and thinking about what non-quantified type they are isomorphic to.</div>
<div><br></div><div>Luke</div></div>