I&#39;d love to see a copy of this go up on hackage for experimentation. Would you care to upload your code, or send it to me so I can upload it?<br><br><div class="gmail_quote">On Sun, Dec 21, 2008 at 12:37 AM, David Menendez <span dir="ltr">&lt;<a href="mailto:dave@zednenem.com">dave@zednenem.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;"><div class="Ih2E3d">On Sat, Dec 20, 2008 at 9:34 PM, Jacques Carette &lt;<a href="mailto:carette@mcmaster.ca">carette@mcmaster.ca</a>&gt; wrote:<br>

&gt; Andrew Wagner wrote:<br>
&gt;&gt;<br>
&gt;&gt; Wadler posted a blog entry the other day about a paper on pattern-matching<br>
&gt;&gt; in Haskell (<a href="http://wadler.blogspot.com/" target="_blank">http://wadler.blogspot.com/</a>). I&#39;ve taken a first stab at turning<br>
&gt;&gt; it into actual code for hackage (<a href="http://hpaste.org/13215" target="_blank">http://hpaste.org/13215</a>). There are two<br>
&gt;&gt; commented-out definitions that don&#39;t type-check, though, and the types are<br>
&gt;&gt; too wild for me to grok. Anybody have any suggestions for 1.) How to fix it<br>
&gt;&gt; and/or 2.) How to use data/type/newtype to simplify the types and make it<br>
&gt;&gt; more manageable? Thanks!<br>
&gt;<br>
&gt; Both errors are because you are using &quot;any&quot; instead of &quot;any&#39;&quot;; you might<br>
&gt; wish to put<br>
&gt; import Prelude hiding any<br>
&gt; at the top of your code, just to avoid such confusion.<br>
<br>
</div>Example 14 also uses (.-&gt;.) where it should use (.&gt;.), and it either<br>
needs some more parentheses or some precedence declarations for the<br>
operators.<br>
<div class="Ih2E3d"><br>
&gt; To make the types more readable (but not necessarily more manageable), I<br>
&gt; have made some changes to my version of this code.<br>
<br>
</div>One oddity in the paper is the type of the failure continuations, ()<br>
-&gt; ans. I&#39;m guessing that&#39;s left over from an earlier phase of<br>
development. In my own transcription of the library, I eliminated the<br>
() parameter without apparent loss of functionality.<br>
<br>
I think I&#39;ve managed to work out the structure of the types, which can<br>
mostly be expressed in modern Haskell.<br>
<br>
The matching part of the patterns have this general form:<br>
<br>
 &nbsp; &nbsp;type PMatch vec vec&#39; ans = (vec -&gt; ans) -&gt; (() -&gt; ans) -&gt; vec&#39; -&gt; ans<br>
<br>
where vec and vec&#39; are the list of argument types before and after the<br>
subpattern match, and ans is the final answer. (In my code, I just use<br>
ans instead of () -&gt; ans for the failure continuation.)<br>
<br>
This gets us:<br>
<br>
nil &nbsp; :: PMatch vec vec ans<br>
one &nbsp; :: a -&gt; PMatch (a,vec) vec ans<br>
(#) &nbsp; :: PMatch vec vec&#39; ans -&gt; PMatch vec&#39; vec&#39;&#39; ans -&gt; PMatch vec vec&#39;&#39; ans<br>
fail &nbsp;:: PMatch vec vec&#39; ans<br>
catch :: PMatch vec vec&#39; ans -&gt; PMatch vec vec&#39; ans -&gt; PMatch vec vec&#39; ans<br>
<br>
These types are less general than the ones Haskell would infer, but<br>
they do not appear to lose any functionality.<br>
<br>
The currying part of the pattern is less easy to analyze. I&#39;ve been<br>
able to use type families to relate the curried and uncurried form of<br>
the function types, but I&#39;m working with GHC 6.8, so it&#39;s possible<br>
this won&#39;t work with the more modern implementations.<br>
<br>
Given the list of argument types and the answer type, generate a<br>
curried function type:<br>
<br>
 &nbsp; &nbsp;type family Curry vec ans<br>
 &nbsp; &nbsp;type instance Curry () ans = ans<br>
 &nbsp; &nbsp;type instance Curry (a,vec) ans = a -&gt; Curry vec ans<br>
<br>
zero, succ zero, and so forth take a function in curried form and<br>
transform it into a function that takes a nested tuple:<br>
<br>
 &nbsp; &nbsp;type CurryDigit vec ans = Curry vec ans -&gt; vec -&gt; ans<br>
<br>
 &nbsp; &nbsp;zero :: CurryDigit () ans<br>
 &nbsp; &nbsp;succ zero :: CurryDigit (a,()) ans<br>
<br>
 &nbsp; &nbsp;succ :: CurryDigit vec ans -&gt; CurryDigit (a,vec) ans<br>
 &nbsp; &nbsp;succ . succ :: CurryDigit vec ans -&gt; CurryDigit (a,(b,vec)) ans<br>
<br>
So the currying part of the pattern will have the form:<br>
<br>
 &nbsp; &nbsp;type PCurry vec vec&#39; ans = CurryDigit vec&#39; ans -&gt; CurryDigit vec ans<br>
<br>
So a pattern has the type,<br>
<br>
 &nbsp; &nbsp;type Pattern a vec vec&#39; ans = (PCurry vec vec&#39; ans, a -&gt; PMatch<br>
vec vec&#39; ans)<br>
<br>
where a is the value being examined, vec and vec&#39; are the list of<br>
unbound argument types before and after the match, and ans is the<br>
result.<br>
<br>
 &nbsp; &nbsp;var :: Pattern a (a,vec) vec ans<br>
 &nbsp; &nbsp;cst :: (Eq a) =&gt; a -&gt; Pattern a vec vec ans<br>
 &nbsp; &nbsp;pair :: Pattern a vec vec&#39; ans -&gt; Pattern b vec&#39; vec&#39;&#39; ans -&gt;<br>
Pattern (a,b) vec vec&#39;&#39; ans<br>
<br>
<br>
Coming from the other side, match takes a value and a case statement<br>
and produces a result:<br>
<br>
 &nbsp; &nbsp;type Case a ans = a -&gt; (() -&gt; ans) -&gt; ans &nbsp; -- or just a -&gt; ans -&gt;<br>
ans in my code<br>
<br>
 &nbsp; &nbsp;match :: a -&gt; Case a ans -&gt; ans<br>
<br>
(|||) combines case statements:<br>
<br>
 &nbsp; &nbsp;(|||) :: Case a ans -&gt; Case a ans -&gt; Case a ans<br>
<br>
and (-&gt;&gt;) creates them from a pattern and a curried function,<br>
<br>
 &nbsp; &nbsp;(-&gt;&gt;) :: Pattern a vec () ans -&gt; Curry vec ans -&gt; Case a ans<br>
<br>
Note that (-&gt;&gt;) requires the pattern to leave no unbound variables<br>
after matching.<br>
<br>
<br>
Given the way everything is polymorphic in ans, it may be possible to<br>
hide it, but I haven&#39;t tried yet.<br>
<div class="Ih2E3d"><br>
<br>
&gt; The principal weakness of these pattern-matching combinators is that there<br>
&gt; is no support for algebraic types, i.e. things like<br>
&gt; data Tree a = Leaf | Branch (Tree a) (Tree a)<br>
&gt; I can see how to use Typeable to deal with that, but is there a simpler way?<br>
<br>
</div>You can define the patterns manually:<br>
<br>
leaf = (id, \v -&gt; case v of { Leaf -&gt; nil; _ -&gt; fail })<br>
<br>
branch p q = (curry_p . curry_q, \v -&gt; case v of { Branch l r -&gt;<br>
match_p l # match_q r; _ -&gt; fail})<br>
 &nbsp; &nbsp;where<br>
 &nbsp; &nbsp;(curry_p, match_p) = p<br>
 &nbsp; &nbsp;(curry_q, match_q) = q<br>
<br>
I assume generating these would be pretty straightforward to automate<br>
with Template Haskell.<br>
<font color="#888888"><br>
--<br>
Dave Menendez &lt;<a href="mailto:dave@zednenem.com">dave@zednenem.com</a>&gt;<br>
&lt;<a href="http://www.eyrie.org/%7Ezednenem/" target="_blank">http://www.eyrie.org/~zednenem/</a>&gt;<br>
</font></blockquote></div><br>