You don't make it clear why you're posting this.

If it's just for comment, that's some impressive work. The compiler is fairly short and is a good demo of how you can do this sort of thing surprisingly quickly if you know what you are doing.

If you intend this as something a lot of people will use, then I'd express very serious concerns about building this on top of Python. Python is one of the slowest languages there is [1]. Putting a mismatching paradigm on top of it is going to cost you some sort of multiplicative slowdown, which could very easily be in the 5x range and could even be in the 20x-50x range. Expect another penalty in memory consumption for what is again already a bit of a memory-using language. It's not long before you've got a language on your hands that is 200-500x slower than C, and perhaps more to the point, 100x slower than Haskell itself. This will make trying to convince anyone else to use it an uphill battle, because while performance isn't everything (Python is perfectly suitable for many uses, of course), insufficient performance is a critical blocker for using it for some project, and performance this bad will be "insufficient performance" for a lot of projects.

Let me be clear that I am NOT pointing this out as a "criticism" of the project. If you are doing this to learn or share some fun stuff, this is irrelevant to you, and let me re-emphasize that you're off to what looks like a good start! I mean this in the spirit of warning you about what may be your biggest problem, depending on your unspecified goals, so you can make good engineering decisions about what to look out for and what to tackle.

One possible solution you could consider is rather than targeting Python AST, which I think your code is doing?, you might consider targeting the bytecode directly. While you're still going to experience a certain amount of paradigm mismatch, you might find this cuts perhaps a 2x out of the multiplicative slowdown stack, gives you more options that Python directly does, and especially in the case of PyPy, may give you the option of examining what bytecode constructs PyPy is better able to optimize and give you some wiggle room in what you emit that you can exploit.

Even if this is just a learning project you may also find you learn useful things by doing this; "emitting bytecode" is a popular option nowadays, with things like LLVM. From emitting bytecode for Python you may even find it not to be too big a leap to emit native code with LLVM, too. A language that automatically works natively when code is implemented in pure lambdascript but transparently interacts with Python would start turning some heads. It's not hard to imagine potentially getting some speedups over Python. Though that's a tougher bar to clear; you've got a typesystem to think about at that point. The code is currently so small and agile it's a good time to start looking at these issues.

[1]: I no longer believe "languages don't have speeds, only implementations do". After many years of trying to speed up the many dynamic scripting languages and generally hitting a wall around 10x-20x slower than C across the board, I now consider the burden of proof that languages do not at least set lower bounds on performance to be on someone who can produce a truly fast-as-C dynamic language interpreter/compiler. (Obligatory LuaJIT callout as the closest to date.)