<br><div class="gmail_quote">On Sat, Dec 31, 2011 at 4:09 PM, Kevin Quick <span dir="ltr">&lt;<a href="mailto:quick@sparq.org">quick@sparq.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
onVarElem :: forall a . (Show a) =&gt; (Maybe a -&gt; String) -&gt; Var -&gt; String<br>
onVarElem f (V1 x) = f x<br>
onVarElem f (V2 x) = f x<br>
<br>
main = putStrLn . onVarElem elemStr $ test<br>
</blockquote>
<br>
This is probably a better design, but still fails for the same reason:<br>
<br>
    Couldn&#39;t match expected type `Int&#39; with actual type `[Char]&#39;<br>
    Expected type: Maybe Int<br>
      Actual type: Maybe String<br>
    In the first argument of `f&#39;, namely `x&#39;<br>
    In the expression: f x</blockquote><div><br></div><div>The problem is the scope of the quantification of the type variable &#39;a&#39;. You can use higher-rank types (via the Rnak2Types or RankNTypes language extension) to achieve what you want. Change the type of &#39;onVarElem&#39; to</div>
<div><br></div><div>    onVarElem :: (forall a . (Show a) =&gt; Maybe a -&gt; String) -&gt; Var -&gt; String</div><div><br></div><div>In contrast to the previous type, this type says that the provided function must be polymorphic over Show instances &#39;a&#39;, while the previous type would have allowed any specialization of &#39;a&#39; with a Show instance.</div>
<div><br></div><div>With the previous type, the call</div><div><br></div><div>    onVarElem (maybe show (show . not))</div><div><br></div><div>would have been legal, with the new type it is not, which is necessary for the implementation to be well typed.</div>
<div><br></div><div>If you don&#39;t want to use a language extension that allows you to require polymorphism on function arguments, then Stephen&#39;s solution is a good workaround.</div><div><br></div><div>Sebastian</div>
</div>