On Thu, Sep 13, 2012 at 8:23 PM, Christopher Howard <span dir="ltr">&lt;<a href="mailto:christopher.howard@frigidcode.com" target="_blank">christopher.howard@frigidcode.com</a>&gt;</span> wrote:<div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

code:<br>
--------<br>
gCore :: Num a =&gt; (a -&gt; a -&gt; a) -&gt; (Integer, Double)<br>
gCore f = (f 1 2, f 2.0 3.0)<br>
--------<br>
<br>
The resulting error is:<br>    Couldn&#39;t match type `Double&#39; with `Integer&#39;<br>
    In the return type of a call of `f&#39;<br>
    In the expression: f 1 2<br>
    In the expression: (f 1 2, f 2.0 3.0)<br></blockquote><div><br></div><div>In standard Haskell, when you write a type signature, there&#39;s an implicit universal quantification of all its type variables:</div><div><br>

</div><div>gCore :: forall a. (Num a =&gt; (a -&gt; a -&gt; a) -&gt; (Integer, Double))</div><div><br></div><div>The problem comes from the parentheses. You have to get past the forall, and you can only do that by picking a value for the type variable. Another way of looking at it is that you aren&#39;t actually required to have a function (a -&gt; a -&gt; a) that works for *all* types a in Num; it only has to work for whatever type you happened to choose for a. In this case, that&#39;s not useful to you, since (+) is defined for all types a in Num, but according to this type signature, the caller is able to pick a type a = Foo and then provide a function of type Foo -&gt; Foo -&gt; Foo.</div>

<div><br></div><div>To get what you want, you need this type signature instead:</div><div><br></div><div>gCore :: (forall a. (Num a =&gt; (a -&gt; a -&gt; a))) -&gt; (Integer, Double)</div><div><br></div><div>Since the forall only covers the type of the parameter, not gCore, the body of gCore isn&#39;t committed to a particular value of a. You only have to commit to a value of a when using the parameter. This also means that the person calling gCore has to pass in a function that works for all types a in Num, rather than just for one, because when they pass that parameter, the value of a hasn&#39;t been chosen yet, since we didn&#39;t have to go inside that forall to get to the point of passing that parameter.</div>

<div><br></div><div>This is not standard Haskell, but it is possible with a language extension supported by GHC called RankNTypes. (Use -XRankNTypes when running ghc or ghci.) There are downsides to using this feature which I am not qualified to fully explain, but the most common problem you&#39;ll find is that type inference fails and an explicit signature is required. (There is also an extension called Rank2Types which covers this particular case, since the forall is only one level deeper than normally allowed.)</div>

<div><br></div><div>-Karl </div></div>