For practice, I’m trying to define a type corresponding to lambda-calculus expressions composed of variables, abstractions, and applications. My current best attempt is:
type expr = Var of string | Abs of expr * expr | App of expr * expr
However, I would like to restrict the first part of an Abs to be a Var. For instance, I would like this to be an ill-formed expr:
Abs(Abs(Var "foo", Var "bar"), Var "bar")
but it is currently accepted as valid. I would also like to require that the first part of an App be an Abs. Is there any way to have the type system enforce these restrictions, or is this pushing it beyond what it was designed to do?
Edit: In case it wasn’t clear, Abs(Var "x", Var "x") should be considered valid.
AFAIU, you need GADTs to achieve that, which were recently merged into svn trunk.
Here is amateur’s example (maybe not fully correct, but it satisfies your requirements) :