A Statement of the Problem

Posted on June 3, 2021

So one of the projects I am working on in my free time when I want to write some code is a Racket/Scheme (some gross syntactical combination of the two) to x86 compiler written in haskell. I can talk more about how its built later, but that isn’t the focus of this post. Recently, I refactored the parsing/lexing from using the monadic parsing library Parsec to using Alex/Happy lexer/parser generators. This allowed me to have a far cleaner AST where I didn’t have to match on lists and such. This is an Improvement. However, what did result is a large mutually recursive data type that defines my AST. My implementation of Lambdas requires a lot of operations on the AST, from folding to find free variables to transformation to naming/renaming each lambda. Obviously writing hundreds of lines of boilerplate for each operation, and then having it be extremely unextensible isn’t the programmer way, much less the haskell way so I set out to find the generic data type manipulator in haskell. I figured, since haskell data types can be pretty much defined as Sum and Product types then there should be some straightforwards way to do it, but it turns out there has been a lot of different strategies written to do this. So I built a sort of mini example of my recursive datatype and set out to find the best solution.

data Sexpr 
    = Expr Expr
    | Const Const
    deriving (Eq, Show)

data Const
    = I Int
    | B Bool
    deriving (Eq, Show)
    
data Expr
    = If Sexpr
    | Lambda String Sexpr
    deriving (Eq, Show)

test = Expr (Lambda "ex" (Const (B True)))

Given an AST like this, I wanted (at the minimum) a library that can take a Sexpr (or a list of Sexpr is probably more ideal) and change the String on the Lambda. Ideally it would also let me thread a simple state monad through it so I can ensure that the symbol is unique across the program.

Haskell has a ton of these; I am not qualified to explain half of them or thier histories, but I will recount what I know as of right now.

When I actually get a full working implementation down, I’ll write it out, but I wanted to list sort of the main ones I found here since I find that there is not a lot of information out there on how to use haskell generics.

Obviously - I have no Idea what I am doing here, and my category theory is weak enough that talk of comonads makes me glaze over slightly. If you want to correct me please email. I will admit however, I wish there were more examples of these libraries, as they are abstract enough that reading documentation is frequently not enough for a newcomer to this field.