<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><div>On Aug 27, 2010, at 8:15 PM, Brandon S Allbery KF8NH wrote:</div><br><blockquote type="cite"><div>You were told about this already: &nbsp;</div></blockquote><div><br></div><div>No doubt I'm being quite dense here. &nbsp;I think your re-explanation may have clicked though:&nbsp;</div><br><blockquote type="cite"><div>because "b" is only mentioned in the<br>result of div2pi, it must be able to return *any* "b" that has a Floating<br>instance.<br><br>But then you say<br><blockquote type="cite">instance (Floating a) =&gt; TwoPi (Foo a) &nbsp;where<br></blockquote><blockquote type="cite"> &nbsp;div2pi (Foo x) = x / (2*pi)<br></blockquote><br>An instance applies to a *specific* type; thus, this instance declaration<br>forces a *specific* type on the result of div2pi, when the class declaration<br>says it must be able to return *any* type.<br><br>Expanding the types, the class declaration says<br><br><blockquote type="cite">div2pi :: forall b. (Floating a, Floating b) =&gt; a -&gt; b<br></blockquote><br>but the instance declares<br><br><blockquote type="cite">div2pi :: (Floating a) =&gt; a -&gt; a<br></blockquote><br>The instance doesn't conform to the class definition; it includes a<br>constraint that the class does not, as the class insists that the type of<br>the result must be independent of the type of the argument, while the<br>instance insists that they must be identical.<br></div></blockquote><div><br></div><div>I've been working on the assumption, perhaps despite attempts to teach me otherwise, that the class is essentially the interface to the rest of the world. &nbsp;That is, the class is the guarantee. &nbsp;The instance, then, can do no less than the class interface has guaranteed. &nbsp;In this case, for example, I've been assuming that the type variable 'b' in my class definition meant "div2pi will result in a value of a type which is an instance of the Floating class". &nbsp;Then, since my instance method resulted in a Float, which is an instance of the Floating class, everything should be happy. &nbsp;If my instance method resulted in a Double, it would be equally happy.</div><div><br></div><div>I think what you're saying is that not only can an instance do no less than the class has guaranteed, it can do no *more*-- meaning the instance can't further restrict the return type even if that return type still conforms to the class definition. &nbsp;In this case returning a Float breaks the class contract because I've gone and said what type of Floating type will be returned. &nbsp;</div><div><br></div><div>The class definition doesn't mean "div2pi can return any type of Floating value", it means "div2pi *will* return any type of floating value".</div><div><br></div><div>I have a harder time working out why returning a "(Floating a) =&gt; a" is seen as different. &nbsp;If I understand what Jürgen was saying, it's because the "a" in this case is specifically the "a" in "Foo a", which nails it down again. &nbsp;If this is right, then my class definition:</div><div><br></div><div><blockquote type="cite">class TwoPi a where<br></blockquote><blockquote type="cite">&nbsp;div2pi :: (Floating b) =&gt; a -&gt; b<br></blockquote><div><br></div>is essentially impossible to conform to because b is completely untethered to anything else in the code and not all "(Floating b)"'s are created equal. &nbsp;I think the intent of the functional dependency in the suggestion you provided in your second email is essentially to tether b to something. &nbsp;Unfortunately if chokes in the second, non-Foo, instance.<br><br></div><div><br></div><div>Am I getting this right? &nbsp;Rereading Jürgen's response, this seems to fit with his explanation as well-- I just didn't grasp it.</div><div><br></div><div>I think I've mistakenly been thinking of instances as more like subclasses, but that's apparently not quite right (thus the "instance" keyword, I suppose).</div><br><blockquote type="cite"><div><br>Perhaps the correct question is "what exactly are you trying to do?"<br><br></div></blockquote><div><br></div><div>I'm literally just trying to understand the type system and its syntax. &nbsp;It's the part of Haskell that feels most foreign, and I'm trying to work through the implications.</div><div><br></div><div>Typeclasses provide a mechanism to abstract operations over multiple types, as you mentioned in the thread for my last question. &nbsp;What I'm trying to figure out now is what kinds of types they can be abstracted over. &nbsp;I'm looking to get the result: &nbsp;"((5.6,Foo 9.8),(0.8912676813146139,1.5597184423005745))"</div><div><br></div><div>From code that looks kind of like this :</div><div><br></div><div><font class="Apple-style-span" face="'Courier New'">data Foo a = Foo a deriving (Show)<br><br>x :: Float<br>x= 5.6<br><br>y :: Foo Double<br>y= Foo 9.8<br><br>class {-something-} TwoPi {-something-} where<br>&nbsp;&nbsp;div2pi :: {-something-}<br><br>instance {-something-} TwoPi Foo where<br>&nbsp;&nbsp;div2pi (Foo b) = b / (2*pi)<br><br>instance TwoPi Float where<br>&nbsp;&nbsp;div2pi a = a / (2*pi)<br><br>main = do<br>&nbsp;&nbsp;print ((x,y),(div2pi x, div2pi y))<br></font><br></div><div>Thanks--</div><div>&nbsp;Greg</div><div><br></div><div><br></div></div><br></body></html>