Good point Ryan,<br><br>I did it in my lunch time and, being in a hurry, overlooked the fact that left adjust in (*2) is redundant and that (*1) can be completely removed by  using (adjust x). I actually think I added (*2) for &quot;safety&quot;!! :-D<br>
<br>R J, you should take a look on Chris Okasaki&#39;s book. This is pretty much what he does all the time to make sure invariants in his data structures are met.<br><br>Best Regards,<br><br>Rafael<br><br><div class="gmail_quote">
On Wed, Mar 4, 2009 at 15:55, Ryan Ingram <span dir="ltr">&lt;<a href="mailto:ryani.spam@gmail.com">ryani.spam@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
2009/3/4 R J &lt;<a href="mailto:rj248842@hotmail.com">rj248842@hotmail.com</a>&gt;:<br>
<div class="im">&gt; What&#39;s the pure solution that uses cases and recursion on<br>
&gt; CatList, not Haskell&#39;s built-in lists, to capture the equality of nested<br>
&gt; CatLists?<br>
<br>
</div>As Rafael pointed out, the simplest thing to do is to convert to a<br>
canonical form; you can prove that each CatList has a single canonical<br>
form and that two equal CatLists always have the same canonical form.<br>
<br>
Something from Rafael&#39;s solution was bugging me, though.<br>
<div class="im">&gt; adjust                           :: CatList a -&gt; CatList a<br>
&gt; adjust (Cat CatNil x) = x<br>
</div>&gt; adjust (Cat x CatNil) = x -- *1<br>
<div class="im">&gt; adjust (Cat (Cat x y) z) = adjust (Cat x (Cat y z))<br>
</div>&gt; adjust (Cat x y) = Cat (adjust x) (adjust y)  -- *2<br>
&gt; adjust x = x<br>
<br>
*2 is the more odd one.  I was sure he had missed a case where the<br>
result of the left &quot;adjust&quot; was incorrect.  But he didn&#39;t; the<br>
interesting thing is that the left adjust is redundant.  The only case<br>
left is &quot;Wrap&quot; which does nothing.<br>
<br>
*1 is a bit odd because it breaks the nice symmetry of the pattern-matching.<br>
<br>
Also, the CatNil cases both fail to adjust the results.<br>
<br>
Here&#39;s my solution:<br>
<br>
&gt; canonical (Cat CatNil xs) = canonical xs<br>
&gt; canonical (Cat (Cat x y) z) = canonical (Cat x (Cat y z))<br>
&gt; canonical (Cat x xs) = Cat x (canonical xs) -- x is &quot;Wrap e&quot; for some e<br>
&gt; canonical (Wrap e) = Cat (Wrap e) CatNil<br>
&gt; canonical CatNil = CatNil<br>
<br>
However, this is basically just converting to a list!  In canonical<br>
form, a CatList always looks like this:<br>
<br>
Cat (Wrap e1) $ Cat (Wrap e2) $ Cat (Wrap e3) $ ... $ CatNil<br>
<br>
&gt; canon_eq CatNil CatNil = True<br>
&gt; canon_eq (Cat (Wrap x) xs) (Cat (Wrap y) ys) = x == y &amp;&amp; canon_eq xs ys<br>
&gt; canon_eq _ _ = False<br>
<br>
&gt; instance Eq a =&gt; Eq (CatList a) where xs == ys = canonical xs `canon_eq` canonical ys<br>
<br>
Gleb&#39;s &quot;viewCL&quot; solution is also interesting, but it is also<br>
equivalent to using lists, due to lazy evaluation.  In fact, an<br>
efficient &quot;toList&quot; on CatLists is just &quot;unfoldr viewCL&quot;.<br>
<div><div></div><div class="h5">_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
</div></div></blockquote></div><br><br clear="all"><br>-- <br>Rafael Gustavo da Cunha Pereira Pinto<br>Electronic Engineer, MSc.<br>