Back when I wanted to write a Lisp interpreter, I thought Haskell would be one of the best languages for it because of its type system. But looking at this code, although I'm sure it's probably very good, it just doesn't strike me as very intuitive or readable. Is this something you get used to over time, like reading Lisp code? Or is it just inherently harder for non-mathematically-minded people to read?
I had the same reaction. The only part of this that I could read was a little surprising:
pop :: CallstackIO ()
pop =
modify popFrame
where popFrame (_:xs) =
xs
popFrame xs =
xs
Not that it's very onerous to implement, but I would expect these "pop" semantics to be imported from some more general type (or trait, or whatever Haskell uses for type composition). That said, I don't know what `modify` means.