
newtype StmtRec = StmtRec (Stmt [StmtRec])
That's pretty much were I threw in the towel last night. Except I had a bunch of places where I had to add the extra constructor statements. I wish there was a solution that didn't require these... they really butcher pattern matching clarity.
will do. More generally, you can use
newtype Fix f = In { out :: f (Fix f) }
and define
type StmtRec = Fix ([] `O` Stmt)
where O denotes composition of functors
newtype O f g a = O (f (g a))
Thanks for that! This provoked some thought on my part about what exactly is going on. I think I could solve this if I added some way to identify that a type parameter is actually referring to the whole type. Say we had a reserved word "fixpoint" for this. Then we'd have something like: data Stmt x = SIf x x then when we actually go to use it, it would be referred to as the type: "Stmt [fixpoint]" Which would get treated exactly like the data declaration: data Stmt = SIf [Stmt] [Stmt] I'll need to add the newtype declaration for the code but I'd be interested if anyone had further thoughts on this topic. I have an implementation of both approaches on a toy parser, but I doubt anyone's interested in seeing that. Michal