<br><br><div class="gmail_quote">On Fri, Apr 30, 2010 at 11:53 PM, Ivan Lazar Miljenovic <span dir="ltr"><<a href="mailto:ivan.miljenovic@gmail.com">ivan.miljenovic@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div class="im">Jason Dagit <<a href="mailto:dagit@codersbase.com">dagit@codersbase.com</a>> writes:<br>
<br>
> On Fri, Apr 30, 2010 at 11:08 PM, Ivan Lazar Miljenovic <<br>
> <a href="mailto:ivan.miljenovic@gmail.com">ivan.miljenovic@gmail.com</a>> wrote:<br>
>><br>
>><br>
>> You're putting the constraint in the wrong places: put the "(Cls a) => "<br>
>> in the actual functions where you need it.<br>
>><br>
><br>
> That's solid advice in general, but it's still not going to work here if any<br>
> of the functions needed for the instance of Graph require the type class<br>
> constraint.<br>
<br>
</div>The Graph class doesn't care what the labels are, so it should matter<br>
about the constraint.<br></blockquote><div><br></div><div>Perhaps this "working" example illustrates the change I want to make. Working in the sense that it type checks but it's a silly example just to illustrate the point:</div>
<div><br></div><div>\begin{code}</div><div><div>{-# LANGUAGE MultiParamTypeClasses #-}</div><div>{-# LANGUAGE FlexibleInstances #-}</div><div>module Graph where</div><div><br></div><div>import Data.Graph.Inductive.Graph hiding (Graph)</div>
<div><br></div><div>-- Defive some arbitrary class, and give it a 'boring'</div><div>-- reason to use it.</div><div>class Cls a where</div><div> boring :: a</div><div><br></div><div>data Blah = Blah</div><div><br>
</div><div>-- Make sure we have at least one instance, but not really needed for this example</div><div>instance Cls Blah where</div><div> boring = Blah</div><div><br></div><div>data B a = B [a]</div><div><br></div><div>
data GrB a b = GrB (B a)</div><div><br></div><div>-- Just copy the bits from FGL that are interesting here</div><div>class Graph gr a b where</div><div> empty :: gr a b</div><div> -- | True if the given 'Graph' is empty.</div>
<div> isEmpty :: gr a b -> Bool</div><div> -- | Create a 'Graph' from the list of 'LNode's and 'LEdge's.</div><div> mkGraph :: [LNode a] -> [LEdge b] -> gr a b</div><div> -- | A list of all 'LNode's in the 'Graph'.</div>
<div> labNodes :: gr a b -> [LNode a]</div><div><br></div><div>instance Cls a => Graph GrB a b where</div><div> empty = GrB (B [boring])</div><div> isEmpty (GrB (B [])) = True</div><div> isEmpty _ = False</div>
<div> mkGraph _ _ = GrB (B [])</div><div> labNodes _ = []</div></div><div>\end{code}</div><div><br></div><div>The Graph class is actually unchanged other than mentioning 'a' and 'b'. This mention of 'a' and 'b' allows instance writers to add contexts other than () when defining instances.</div>
<div><br></div><div>Jason</div></div>