Point being, nobody wants to model their data structures as pure lambdas; even primitive integers are an addition on top of the lambda calculus.
> For an example of a non-trivial program
I don't think I'm taking the point you wanted me to from this program. It's under 30 lines, yet I'd need to pore over this for twice as many minutes to comprehend what it's doing. I can see the lambda abstractions and applications clear as day, but what they're doing I couldn't say. (The comments clearly say it's a universal binary LC interpreter, but we don't usually judge languages by their comments.)
EDIT: Right, okay, it's a submission to the the International Obfuscated C Code Contest. If it's obfuscated, then indeed, I'm not meant to comprehend it easily. Not sure that sells the lambda calculus.
Not that much less, since you can manually translate back your Haskell code to lambda calculus. E.g. your
List a = Nil | Cons a (List a)
rewrites to let
Nil = \n\c. n
Cons = \x\y. \n\c. c x y
in ...
Of course the type system is what helps you write correct Haskell code in the first place, so the untyped lambda calculus will be painful for debugging wrongly typed code.Also, in lambda calcalus there is no recursion built-in. You have to build it yourself with the Y combinator.
let Y = \f. (\x. x x) (\x. f (x x)) in program-using-Y
which is the slightly more legible version of
(\Y. program-using-Y) (\f. (\x. x x) (\x. f (x x))
But much less high with the lambda calculus than with the other two; Haskell is not far from being a layer of syntactic sugar on top of the lambda calculus.
For an example of a non-trivial lambda calculus program, see this self-interpreter [1] for binary lambda calculus [2].
[1] https://github.com/tromp/AIT/blob/master/uni.lam
[2] https://www.ioccc.org/2012/tromp/hint.html