Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I can't say with too much authority on this subject, but here's what I think may be happening:</p> <p>Consider what the typechecker has to do in each of these cases. <code>(print . runST)</code> has type <code>Show b =&gt; (forall s. ST s t) -&gt; IO ()</code>. <code>fourty_two</code> has type <code>ST x Int</code>. </p> <p>The <code>forall</code> here is an existential type qualifier - here it means that the argument passed in has to be <em>universal</em> on <code>s</code>. That is, you must pass in a polymorphic type that supports any value for <code>s</code> whatsoever. If you don't explicitly state <code>forall</code>, Haskell puts it at the outermost level of the type definition. This means that <code>fourty_two :: forall x. ST x Int</code> and <code>(print . runST) :: forall t. Show t =&gt; (forall s. ST s t) -&gt; IO ()</code></p> <p>Now, we can match <code>forall x. ST x Int</code> with <code>forall s. ST s t</code> by letting <code>t = Int, x = s</code>. So the direct call case works. What happens if we use <code>$</code>, though?</p> <p><code>$</code> has type <code>($) :: forall a b. (a -&gt; b) -&gt; a -&gt; b</code>. When we resolve <code>a</code> and <code>b</code>, since the type for <code>$</code> doesn't have any explicit type scoping like this, the <code>x</code> argument of <code>fourty_two</code> gets lifted out to the outermost scope in the type for <code>($)</code> - so <code>($) :: forall x t. (a = forall s. ST s t -&gt; b = IO ()) -&gt; (a = ST x t) -&gt; IO ()</code>. At this point, it tries to match <code>a</code> and <code>b</code>, and fails.</p> <p>If you instead write <code>((print . runST) $) fourty_two</code>, then the compiler first resolves the type of <code>((print . runST $)</code>. It resolves the type for ($) to be <code>forall t. (a = forall s. ST s t -&gt; b = IO ()) -&gt; a -&gt; b</code>; note that since the second occurance of <code>a</code> is unconstrained, we don't have that pesky type variable leaking out to the outermost scope! And so the match succeeds, the function is partially applied, and the overall type of the expression is <code>forall t. (forall s. ST s t) -&gt; IO ()</code>, which is right back where we started, and so it succeeds.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload