Tuesday, 13 February 2007

Pattern guards in Liskell

Yes, I'm working on documentation this very moment, but after seeing A missing Haskell feature on Planet Haskell, I was unable to resist. I need my daily dosage of coding.

Here is working Liskell syntax sugar for pattern guards as described by Neil Mitchell.
(defmacro (~= pts)
`(let (((comp ,pts) True)
((comp _) False))
comp))
It can be used right-away as in:
(all (~= Star _) ([] (Star "x") (Atom)))       -> False
(all (~= Star _) ([] (Star "x") (Star "foo"))) -> True
To give you a brief idea why this works: The function body of defmacro is called with a list (called pts) that is bound to ([] (PSym "Star") (PSym "_")) which is equivalent to [PSym "Star", PSym "_"] written in Haskell syntax. This parse tree part is substituted into the backquoted code template at ,pts, resulting in the parse tree:
(let (((comp (Star _) True))          | let comp (Star _) = True
((comp _) False)) | comp _ = False
comp) | in comp
The Haskell equivalent of the generated Liskell parse tree is shown on the right hand side for our Planet Haskell readers. This generated parse tree is the result of the compile-time "~=" macro transformation, and instead of the original (~= Star _) expression the generated parse tree is compiled to object code.

You can compile Star.lsk with "ghc Star.lsk -o Star -main-is Star -package LskPrelude".

(For those who already have a local Liskell branch, please pull the latest changes and redo ./darcs-all get. I moved the LskPrelude into a separate new core package. Also I vastly simplified the parse tree type, so the Liskell paper is not correct anymore wrt this.)

No comments: