SHPLIT is the Strathclyde Haskell Pattern LIsting Tool. It makes use of type information to figure out how to split a pattern variable into its possible constructor forms. It's at a rather experimental stage, just now, so caveat emptor. This directory is also a darcs repo.
The main shplit executable is a transducer, taking a .hs file (sorry, no .lhs yet) from stdin and splatting a modified version of the same to stdout. The associated lump of emacs lisp, if suitably pasted into your .emacs, or whatever, should enable you to process the buffer with M-x shplit-buffer, or attack the variable at point with M-x shplit-this (bound to C-c C-c).
SHPLIT knows about a few standard datatypes, and the datatypes declared in the input. A future version might be kind enough to chase modules. SHPLIT can't handle records or GADTs. SHPLIT works only on top-level prefix functions with an explicit (Hindley-Milner) type signature. It's for beginners, just now.
To indicate that you want to shplit a pattern variable, just bung {-?-} in the source code after it. Like this
foo :: [x] -> [x] foo xs{-?-} =Note that the = is needed as a clue that it's a program line, but a right-hand side is not compulsory (and will be crudely copied). You should get
foo :: [x] -> [x] foo [] = foo (x : xs) =back. SHPLIT tries to be slightly cunning with names, and is happy to do more than one shplit at a time.
goo :: [x] -> [x] -> [x] goo xs{-?-} ys{-?-} =yields
goo :: [x] -> [x] -> [x] goo [] [] = goo [] (y : ys) = goo (x : xs) [] = goo (x : xs) (y : ys) =
There's plenty of room for improvement. It only took me a day to knock it together. But it's fun to play with.
If you just write any old Haskell 98 datatype, SHPLIT will make up a vaguely sensible naming scheme, but you can roll your own, by annotating your datatype declaration. Here's what I used for lists.
data {-xs-}[] x = [] | {-x-}x : {-xs-}[x]The annotation on the type head is a crude string pattern. All but the first character match one character of the variable being split, and the first character matches any remaining prefix. So matching xs against a pattern variable yss would bind x to ys and s to itself. If the pattern variable is too short, the overhanging characters match themselves, so matching xs against l would bind s to l and x to itself. The resulting substitutions are then applied to the name annotations which accompany each constructor argument. So if the pattern variable is yss, it splits as [] or (ys : yss).