On Mon, Jul 25, 2011 at 1:40 PM, Jacques Carette <span dir="ltr"><<a href="mailto:carette@mcmaster.ca">carette@mcmaster.ca</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<u></u>
<div text="#000000" bgcolor="#ffffff"><div class="im">
On 25/07/2011 9:55 AM, Edward Kmett wrote:<br>
<blockquote type="cite">
<div class="gmail_quote">
<div>
<div style="color:rgb(0, 0, 0)">
<span style="color:rgb(31, 73, 125)">If you have an associative (+), then you can use
(.*) to multiply by a whole number, </span><span style="color:rgb(31, 73, 125)">I
currently do fold a method into the Additive class to
'fake' a LeftModule, but you have to explicitly use it.</span></div>
<div><font color="#1f497d"><br>
</font></div>
<div style="color:rgb(0, 0, 0)"><span style="color:rgb(31, 73, 125)">class
Additive m => LeftModule r m</span></div>
<div style="color:rgb(0, 0, 0)">
<span style="color:rgb(31, 73, 125)">class LeftModule Whole m => Additive m</span></div>
<div style="color:rgb(0, 0, 0)"><span style="color:rgb(31, 73, 125)"><br>
</span></div>
<div style="color:rgb(0, 0, 0)"><span style="color:rgb(31, 73, 125)">This
says that if you have an Additive semigroup, then there
exists a LeftModule over the whole numbers, and that every
leftmodule is additive, but there can exist other
LeftModules than just ones over the whole numbers! </span></div>
<div style="color:rgb(0, 0, 0)"><span style="color:rgb(31, 73, 125)"><br>
</span></div>
<div style="color:rgb(0, 0, 0)"><span style="color:rgb(31, 73, 125)">Given
LeftModule Integer m, you'd know you have </span><span style="color:rgb(31, 73, 125)">Additive
m </span><span style="color:rgb(31, 73, 125)">and LeftModule Whole m.</span></div>
<div style="color:rgb(0, 0, 0)"><span style="color:rgb(31, 73, 125)"><br>
</span></div>
<div style="color:rgb(0, 0, 0)"><span style="color:rgb(31, 73, 125)">LeftModule
Integer m => LeftModule Whole m <=> Additive m.</span></div>
</div>
</div>
</blockquote>
<br></div>
I believe that part of the issue here is that you are using a single
relation (given by class-level => ) to model what are actually
two different relations: a 'constructive' inclusion and a 'view' (to
use the terminology from the Specifications community, which is
clearly what these class definitions are).<br>
<br>
Just like inheritance hierarchies fail miserably when you try to
model more than one single relation, it should not be unsurprising
that the same thing befalls '=>', which is indeed a (multi-ary)
relation.<br>
<br>
In my own hierarchy for Algebra, I use two relations. Slightly
over-simplifying things, one of them reflects 'syntactic' inclusion
while the other models 'semantic' inclusion. There are very strict
rules for the 'syntactic' one, so that I get a nice hierarchy and
lots of free theorems, while the semantic one is much freer, but
generates proof obligations which must be discharged. The syntactic
one generates a nice DAG (with lots of harmless diamonds), while the
semantic one is a fully general graph.<br>
<br>
Here is another way to look at it: when you say<div class="im"><br>
class LeftModule Whole m => Additive m<br></div>
you are closer to specifying an *instance* relation than a *class
constraint* relation. </div></blockquote><div><br></div><div>This is very true. </div><div><br></div><div>However, as mentioned at the outset specifying such instance requires newtype noise (on m, to avoid incoherent overlap with the other instances) that leads to a particularly hideous programming style.</div>
<div><br></div><div>newtype NaturalModule m = NaturalModule { runNaturalModule :: m }</div><div><br></div><div>instance Monoidal m => LeftModule Natural (NaturalModule m) where</div><div><br></div><div>It isn't so bad when working with simple examples like</div>
<div><br></div><div>fiveTimes m = runNaturalModule (5 .* NaturalModule m)</div><div><br></div><div>but it gets progressively worse as the hierarchy gets deeper, and I have to deal with putting on and taking off more and more of these silly wrappers.</div>
<div><br></div><div>Placing the superclass constraint enforces that such instances will always be available to me, and admits optimized implementations, which I currently have to shoehorn into the main class and expose by convention.</div>
<div><br></div><div>-Edward</div></div>