Are there any Haskell programmers here? I know there’s at least one more, but how many of us are there? How about we share some (not so?) obscure tips/hacks/type magic/language extensions etc.
I’ve just come across a cool extension to GHC: view patterns. I’ve been aware of Wadler’s proposal (and the paper that inspired it) for a while, but I didn’t realise they’d actually implemented it in GHC.
View patterns fix a really irritating problem: sometimes you want to keep the particular representation of a datatype fully abstract, for instance, to maintain an invariant, or whatever. However, when using the datatype in other modules, it’s sometimes convenient (necessary!) to be able to pattern match against it. The only way to do this is to break abstraction and expose the particular implementation.
With view patterns, you define two datatypes. One, the “real one”, is kept fully abstract. The other is the “view” datatype, and is exported from a module. A “view” function is also defined, translating between the two, and this gets executed when pattern matching. For instance:
module List(List, ListView (..), view) where data List a = Empty | Cons a (List a) data ListView a = Empty | Cons a (List a) view :: List a -> ListView a view Empty = Empty view Cons hd tl = Cons hd tl
(The example is a bit stupid, as both representations are identical, but this needn’t be so.)
Now, pattern matching against a list in another module, we have:
reverse :: List a -> List a reverse (view -> Empty) = Empty reverse (view -> Cons hd tl) = etc.
Another cool thing I’ve just come across is hlint, a lint-like tool for Haskell. You can install it using apt-get if on Ubuntu. It not only points out stylistic stuff, like excess parentheses, but also points out simplifications of your code, using higher-order functions, or converting it into point-free style. I’ve already come across a few useful higher-order functions (mostly from Control.Arrow) by using it which I didn’t know how to use before.
So, got any other cool tricks?