Church, Curry, and the code around the code

Consider these two lambda terms:

lambda x : Int  . x
lambda x : Bool . x

Now erase the annotations:

lambda x . x

Did we forget something about one term, or did we collapse two different terms into one?

Church-style and Curry-style typing give different answers to that question. In a Church-style presentation, the annotated terms are the objects being studied. The type annotation is part of the syntax, so the two identity functions above are different typed objects. They may erase to the same untyped term, but erasure is a translation, not equality.

In a Curry-style presentation, the untyped term is the object being studied. The type system makes judgments about it:

lambda x . x : Int  -> Int
lambda x . x : Bool -> Bool
lambda x . x : A    -> A

So the difference is not only whether the programmer writes annotations. It is a difference in what the theory treats as the program. Church-style typing builds type information into the term language. Curry-style typing keeps the raw term language smaller, then assigns types by a separate relation. That difference affects equality, erasure, inference, elaboration, and the shape of the metatheory.

Once this distinction is visible, similar placement questions start appearing in ordinary codebases. A codebase is rarely just executable code. It also contains claims about the code: types, tests, examples, documentation, contracts, comments, specifications. Different ecosystems put those claims at different distances from the program.

Modern type systems give familiar examples. In Rust or TypeScript, type syntax is part of the source language and the compiler understands it. In Python, type annotations are parsed and preserved, but the core language does not act on them in any way. In JSDoc, type information lives in comments. In TypeScript declaration files, type information can live in separate .d.ts files. The same happens in Ruby and its .rbs files.

The same pattern appears outside types. Python docstrings are real syntax: the first string in a function body becomes documentation metadata. JSDoc documentation is written as comments for external tools. Racket documentation is commonly written in Scribble, a separate documentation language. Literate programming reverses the usual relationship even further: the document becomes the main artifact, and code is extracted from it. Tests also move around: Rust and Racket often keep small tests near the code, while most ecosystems put tests in separate files or directories.

These examples are not all instances of Church-style or Curry-style typing in the formal sense. They are ordinary versions of the same placement problem. Some facts are pulled into the object language. Some facts sit in comments, sidecar files, test suites, documentation systems, or external tools.


References

This is like a reading map for the idea and its afterlife.




return home