<div>I sent this message yesterday to Bulat&nbsp;but it was intended for the haskel cafe, so I&#39;m resending it here today.</div>
<div>&nbsp;</div>
<div>Thank to&nbsp;everyone&nbsp;who answered me privately. Today I&#39;ll keep on experimenting and read the reference you gave me.</div>
<div>&nbsp;</div>
<div>Cristiano</div>
<div><br>---------- Forwarded message ----------<br><span class="gmail_quote">From: <b class="gmail_sendername">Cristiano Paris</b> &lt;<a href="mailto:cristiano.paris.ml@gmail.com">cristiano.paris.ml@gmail.com</a>&gt;<br>
Date: Jun 21, 2007 6:20 PM<br>Subject: Re: Type classes vs C++ overloading Re: [Haskell-cafe] Messing around with types [newbie]<br>To: Bulat Ziganshin &lt;<a href="mailto:Bulat.Ziganshin@gmail.com">Bulat.Ziganshin@gmail.com
</a>&gt;<br><br>&nbsp;</span></div>
<div><span class="q"><span class="gmail_quote">On 6/21/07, <b class="gmail_sendername">Bulat Ziganshin</b> &lt;<a onclick="return top.js.OpenExtLink(window,event,this)" href="mailto:bulat.ziganshin@gmail.com" target="_blank">
bulat.ziganshin@gmail.com</a>&gt; wrote:</span> 
<blockquote class="gmail_quote" style="PADDING-LEFT: 1ex; MARGIN: 0px 0px 0px 0.8ex; BORDER-LEFT: #ccc 1px solid">Hello Cristiano,<br><br>Thursday, June 21, 2007, 4:46:27 PM, you wrote:<br><br>&gt; class FooOp a b where<br>
&gt; foo :: a -&gt; b -&gt; IO ()<br>&gt;<br>&gt; instance FooOp Int Double where<br>&gt; foo x y = putStrLn $ (show x) ++ &quot; Double &quot; ++ (show y)<br><br>this is rather typical question :)&nbsp;</blockquote>
<div>&nbsp;</div></span>
<div>I knew it was... :D</div>
<div><span class="e" id="q_1134f1583a801b44_3"><br>
<blockquote class="gmail_quote" style="PADDING-LEFT: 1ex; MARGIN: 0px 0px 0px 0.8ex; BORDER-LEFT: #ccc 1px solid">&nbsp;unlike C++ which resolves any<br>overloading at COMPILE TIME, selecting among CURRENTLY available<br>overloaded definitions and complaining only when when this overloading 
<br>is ambiguous, type classes are the RUN-TIME overloading mechanism<br><br>your definition of partialFoo compiled into code which may be used<br>with any instance of foo, not only defined in this module. so, it<br>cannot rely on that first argument of foo is always Int because you may 
<br>define other instance of FooOp in other module. &quot;10&quot; is really<br>constant function of type:<br><br>10 :: (Num t) =&gt;&nbsp;&nbsp;t<br><br>i.e. this function should receive dictionary of class Num in order to<br>return value of type t (this dictionary contains fromInteger::Integer-&gt;t 
<br>method which used to convert Integer representation of 10 into type<br>actually required at this place)<br><br>this means that partialFoo should have a method to deduce type of 10<br>in order to pass it into foo call. Let&#39;s consider its type: 
<br><br>partialFoo :: (FooOp t y) =&gt;&nbsp;&nbsp;y -&gt; IO ()<br><br>when partialFoo is called with *any* argument, there is no way to<br>deduce type of t from type of y which means that GHC has no way to<br>determine which type 10 in your example should have. for example, if 
<br>you will define<br><br>instance FooOp Int32 Double where<br><br>anywhere, then call partialFoo (5.0::Double) will become ambiguous<br><br>shortly speaking, overloading resolved based on global class<br>properties, not on the few instances present in current module. OTOH, 
<br>you build POLYMORPHIC functions this way while C++ just selects<br>best-suited variant of overloaded function and hard-code its call<br><br>further reading:<br><a onclick="return top.js.OpenExtLink(window,event,this)" href="http://homepages.inf.ed.ac.uk/wadler/papers/class/class.ps.gz" target="_blank">
http://homepages.inf.ed.ac.uk/wadler/papers/class/class.ps.gz</a><br><a onclick="return top.js.OpenExtLink(window,event,this)" href="http://haskell.org/haskellwiki/OOP_vs_type_classes" target="_blank">http://haskell.org/haskellwiki/OOP_vs_type_classes
</a><br>chapter 7 of GHC user&#39;s guide, &quot;functional dependencies&quot; </blockquote>
<div>&nbsp;</div></span></div></div>
<div>Mmmmmhhhh... your point is hard to understand for me.<br>&nbsp;</div>
<div>In his message, I can understand Bryan Burgers&#39; point better (thanks Bryan) and I think it&#39;s somewhat right even if I don&#39;t fully understand the type machinery occuring during ghc compilation (yet).</div>

<div>&nbsp;</div>
<div>Quoting Bryan:</div>
<div>&nbsp;</div>
<div>&quot;<em>From this you can see that 10 is not necessarily an Int, and 5.0 is<br></em>not necessarily a Double. So the typechecker does not know, given just<br>10 and 5.0, which instance of &#39;foo&#39; to use. But when you explicitly 
<br>told the typechecker that 10 is an Int and 5.0 is a Double, then the<br>type checker was able to choose which instance of &#39;foo&#39; it should use.&quot;</div>
<div>&nbsp;</div>
<div>So, let&#39;s see if I&#39;ve understood how ghc works:</div>
<div>&nbsp;</div>
<div>1 - It sees 5.0, which belongs to the Fractional class, and so for 10 belonging to the Num class.</div>
<div>2 - It only does have a (FooOp x y) instance of&nbsp;foo&nbsp;where x = Int and&nbsp;y = Double but it can&#39;t tell whether 5.0 and 10.0 would fit in the Int and Double types (there&#39;s some some of uncertainty here).</div>
<div>3 - Thus, ghci complains.</div>
<div>&nbsp;</div>
<div>So far so good. Now consider the following snippet:</div>
<div>&nbsp;</div>
<div>module Main where</div>
<div>
<p>foo :: Double -&gt; Double<br>foo = (+2.0)</p>
<p>bar = foo 5.0<br><br>I specified intentionally the type signature of foo. Using the same argument as above, ghci should get stuck in evaluating foo 5.0 as&nbsp;it may not be a Double, but only a Fractional. Surprisingly (at least to me) it works! 
</p>
<p>So, it seems as if the type of 5.0 was induced by the type system to be Double as foo accepts only Double&#39;s.</p>
<p>If I understand well, there&#39;s some sort of asymmetry when typechecking a function application (the case of foo 5.0), where the type signature of a function is dominant, and where typechecking an overloaded function application (the original case) since there type inference can&#39;t take place as someone could add a new overloading later as Bulat says. 
</p>
<p>So, I tried to fix my code and I came up with this (partial) solution:</p>
<p>module Main where</p><span class="q">
<p>class FooOp a b where<br>&nbsp; foo :: a -&gt; b -&gt; IO ()</p></span>
<p>instance (Num t) =&gt; FooOp t Double where<span class="q"><br>&nbsp; foo x y = putStrLn $ (show x) ++ &quot; Double &quot; ++ (show y)</span></p>
<p>partialFoo :: Double -&gt; IO ()<br>partialFoo = foo 10</p>
<p>bar = partialFoo 5.0</p>
<p>As you can see, I specified that partialFoo does accept Double so the type of 5.0 if induced to be Double by that type signature and the ambiguity disappear (along with relaxing the type of a to be simply a member of the Num class so 10 can fit in anyway). 
</p>
<p>Problems arise if I add another instance of FooOp where b is Int (i.e. FooOp Int Int):</p>
<p>module Main where</p><span class="q">
<p>class FooOp a b where<br>&nbsp; foo :: a -&gt; b -&gt; IO ()</p></span>
<p>instance (Num t) =&gt; FooOp t Double where<span class="q"><br>&nbsp; foo x y = putStrLn $ (show x) ++ &quot; Double &quot; ++ (show y)</span></p>
<p>instance (Num t) =&gt; FooOp t Int where<br>&nbsp; foo x y = putStrLn $ (show x) ++ &quot; Int &quot; ++ (show y)</p>
<p>partialFoo = foo 10</p>
<p>bar = partialFoo (5.0::Double)<br><br>while I thought&nbsp;could be solved likewise:</p>
<p>module Main where</p><span class="q">
<p>class FooOp a b where<br>&nbsp; foo :: a -&gt; b -&gt; IO ()</p></span>
<p>instance (Num t1, Fractional t2) =&gt; FooOp t1 t2 where<span class="q"><br>&nbsp; foo x y = putStrLn $ (show x) ++ &quot; Double &quot; ++ (show y)</span></p>
<p>instance (Num t1, Num t2) =&gt; FooOp t1 t2 where<br>&nbsp; foo x y = putStrLn $ (show x) ++ &quot; Int &quot; ++ (show y)</p>
<p>partialFoo = foo 10</p>
<p>bar = partialFoo 5.0</p>
<p>but it didn&#39;t work. Here&#39;s ghci&#39;s complaint:</p>
<p>example.hs:7:0:<br>&nbsp;&nbsp;&nbsp; Duplicate instance declarations:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; instance (Num t1, Fractional t2) =&gt; FooOp t1 t2<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- Defined at example.hs:7:0<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; instance (Num t1, Num t2) =&gt; FooOp t1 t2<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- Defined at 
example.hs:10:0<br>Failed, modules loaded: none.</p>
<p>It seems that Num and Fractional are somewhat related. Any hint? Were my reasonings correct or was it only crap?</p>
<p>Thanks,</p>
<p>Cristiano</p></div>