Disadvantages





Only implemented in GHC - sorry to the poor Hugs users

Requires rank-2 types, which means its not actually Haskell 98



Occassionally the rank-2-ness infects the code you write, with unfortunate error messages (although this is not that common)

A data structure









Queries

Traversals

At the moment I'm working on a boilerplate removal for Haskell, which is faster (runtime), shorter (code), more type safe and requires fewer extensions than Scrap Your Boilerplate (SYB). However, since I haven't finished and released a stable version, I can't really recommend people use that. The reason I started working on this is because I was unaware of SYB when I started. Last week I also introduced someone to SYB, who had done quite a bit of Haskell programming, but had not stumbled across SYB. As a result, I think it needs a bit more attention - SYB is one of the strengths of Haskell!Before saying how great SYB is, its important to point out the things that make it not so great:Before showing some operations, I'm going to first introduce a data structure on which we can imagine operations are performed. I don't like the example from the SYB benchmark - it feels like an XML file (as is the stated intention), which means that the logic behind it is a bit disturbed. So instead I'll pick a data type like an imperative programming language:{-# OPTIONS_GHC -fglasgow-exts #-}import Data.Genericsdata Expr = Var String | Lit Int | Call String [Expr] deriving (Data, Typeable)data Stmt = While Expr [Stmt] | Assign String Expr | Sequence [Stmt] deriving (Data,Typeable)We define the data type as normal, adding deriving for Data and Typeable - the two key SYB types. We also add an import and a flag, just to get the GHC machinery working for the derivings.So lets imagine you have to get a list of all literals. In SYB this is easy:extractLits :: Data a => a -> [Int]extractLits = everything (++) ([] `mkQ` f)where f (Lit x) = [x] ; f _ = []Wow, easy! This function will operate on anything which has a Data instance, so you can run it on an Expr, Stmt, [Stmt], [Either Stmt Expr] - the choice is yours. For the purposes of a short introduction, I'd recommend treating all the bits except the "f" as just something you write - read the full SYB paper to get all the details of what everything can be used for.Now lets negate all the literals, we have:negateLits :: Data a => a -> anegateLits = everywhere (mkT f)where f (Lit x) = Lit (negate x) ; f x = xAgain, its pretty easy. And once again, consider all apart from the "f" as just something you write.The gains in code reduction that can be made with SYB are quite substantial, and by removing the boilerplate you get code which can be reused more easily. Boilerplate code is bad, and should be removed where necessary.