To my understanding, what you want is pattern matching on data constructors. In the following example,

data Expr = Num Int
          | Plus  Expr Expr
          | Minus Expr Expr

incrementNums :: Expr -> Expr
incrementNums (Num i) = Num (i+1)
incrementNums (Plus  i j) = Plus  (incrementNums i) (incrementNums j)
incrementNums (Minus i j) = Minus (incrementNums i) (incrementNums j)

incrementNums' :: Expr -> Expr
incrementNums' (Num i) = Num (i+1)
incrementNums' (cons i j) = cons (incrementNums' i) (incrementNums' j)

You want incrementNums' instead of incrementNums.

And that's not possible with this data type. Of course you can always do the following:

data ExprEnum = Plus | Minus

data Expr = Num Int
          | BinExpr ExprEnum Expr Expr

incrementNums :: Expr -> Expr
incrementNums (Num i) = Num (i+1)
incrementNums (BinExpr cons i j) = BinExpr cons (incrementNums i) (incrementNums j)

Hope this helps. Cheers,

On 3 August 2010 12:51, Matt Andrew <mjsaand@gmail.com> wrote:
Hi all,

I am in the process of writing a Scheme interpreter/compiler in Haskell as my first serious project after learning the basics of Haskell. The goal is to really get a feel for Haskell. I am trying to accomplish this as much as I can on my own, but am referring to Jonathan Tang's 'Write Yourself a Scheme in 48 hours' whenever I get really stuck.

I have a question regarding a pattern that I have found within my code for which I cannot seem to find an abstraction.

I am implementing some of the primitive Scheme type-checker functions with the following code:

numberP :: SchemeVal -> SchemeVal
numberP (Number _) = Bool True
numberP _          = Bool False

boolP :: SchemeVal -> SchemeVal
boolP (Bool _) = Bool True
boolP _        = Bool False

symbolP :: SchemeVal -> SchemeVal
symbolP (Atom _) = Bool True
symbolP _        = Bool False

This is a pattern that I could easily provide an abstraction for with a Lisp macro, but I'm having trouble discovering if/how it's possible to do so elegantly in Haskell. The closest (but obviously incorrect) code to what I'm trying to accomplish would be:

typeChecker :: SchemeVal -> SchemeVal -> SchemeVal
typeChecker (cons _) (cons2 _) = Bool $ cons == cons2

I understand this code drastically misunderstands how pattern matching works, but (hopefully) it expresses what I'm trying to accomplish. Anyone have any suggestions?

I do realise that such an abstraction is barely worth it for the amount of code it will save, but this exercise is about learning the ins and outs of Haskell.

Appreciate you taking the time to read this,

Matt Andrew
_______________________________________________
Beginners mailing list
Beginners@haskell.org
http://www.haskell.org/mailman/listinfo/beginners



--
Ozgur Akgun