Syntax and combinators for manipulating algebraic data types