<br><br><div class="gmail_quote">On Mon, Aug 13, 2012 at 12:30 PM, Jay Sulzberger <span dir="ltr">&lt;<a href="mailto:jays@panix.com" target="_blank">jays@panix.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Does Haskell have a word for &quot;existential type&quot; declaration?  I<br>
have the impression, and this must be wrong, that &quot;forall&quot; does<br>
double duty, that is, it declares a &quot;for all&quot; in some sense like<br>
the usual &quot;for all&quot; of the Lower Predicate Calculus, perhaps the<br>
&quot;for all&quot; of system F, or something near it.<br></blockquote></div><br>It&#39;s using the forall/exists duality:<br>    exsts a. P(a)  &lt;=&gt;  forall r. (forall a. P(a) -&gt; r) -&gt; r<br><br>For example:<br>
    (exists a. Show a =&gt; a) &lt;=&gt; forall r. (forall a. Show a =&gt; a -&gt; r) -&gt; r<br><br>This also works when you look at the type of a constructor:<br><br>    data Showable = forall a. Show a =&gt; MkShowable a<br>
    -- MkShowable :: forall a. Show a =&gt; a -&gt; Showable<br><br>    caseShowable :: forall r. (forall a. Show a =&gt; a -&gt; r) -&gt; Showable -&gt; r<br>    caseShowable k (MkShowable x) = k x<br><br>    testData :: Showable<br>
    testData = MkShowable (1 :: Int)<br>    <br>    useData :: Int<br>    useData = case testData of (MkShowable x) -&gt; length (show x)<br><br>    useData2 :: Int<br>    useData2 = caseShowable (length . show) testData<br>
<br>Haskell doesn&#39;t currently have first class existentials; you need to wrap them in an existential type like this.  Using &#39;case&#39; to pattern match on the constructor unwraps the existential and makes any packed-up constraints available to the right-hand-side of the case.<br>
<br>An example of existentials without using constraints directly:<br><br>    data Stream a = forall s. MkStream s (s -&gt; Maybe (a,s))<br><br>    viewStream :: Stream a -&gt; Maybe (a, Stream a)<br>    viewStream (MkStream s k) = case k s of<br>
        Nothing -&gt; Nothing<br>        Just (a, s&#39;) -&gt; Just (a, MkStream s&#39; k)<br><br>    takeStream :: Int -&gt; Stream a -&gt; [a]<br>    takeStream 0 _ = []<br>    takeStream n s = case viewStream s of<br>
        Nothing -&gt; []<br>        Just (a, s&#39;) -&gt; a : takeStream (n-1) s&#39;<br><br>    fibStream :: Stream Integer<br>    fibStream = Stream (0,1) (\(x,y) -&gt; Just (x, (y, x+y)))<br><br>Here the &#39;constraint&#39; made visible by pattern matching on MkStream (in viewStream) is that the &quot;s&quot; type stored in the stream matches the &quot;s&quot; type taken and returned by the &#39;get next element&#39; function.  This allows the construction of another stream with the same function but a new state -- MkStream s&#39; k.<br>
<br>It also allows the stream function in fibStream to be non-recursive which greatly aids the GHC optimizer in certain situations.<br><br>  -- ryan<br>