Reserved Notation "'slet' x .. y := A 'in' b"
  (at level 200, x binder, y binder, b at level 200, format "'slet'  x .. y  :=  A  'in' '//' b").
Reserved Notation "T x [1] = { A } ; 'return' ( b0 , b1 , .. , b2 )"
  (at level 200, format "T  x [1]  =  { A } ; '//' 'return'  ( b0 ,  b1 ,  .. ,  b2 )").

Delimit Scope ctype_scope with ctype.
Local Open Scope ctype_scope.
Delimit Scope expr_scope with expr.
Inductive base_type := TZ | TWord (logsz : nat).
Inductive flat_type := Tbase (T : base_type) | Prod (A B : flat_type).
Context {var : base_type -> Type}.
Fixpoint interp_flat_type (interp_base_type : base_type -> Type) (t :
flat_type) :=
  match t with
  | Tbase t => interp_base_type t
  | Prod x y => prod (interp_flat_type interp_base_type x) (interp_flat_type
interp_base_type y)
  end.
Inductive exprf : flat_type -> Type :=
| Var {t} (v : var t) : exprf (Tbase t)
| LetIn {tx} (ex : exprf tx) {tC} (eC : interp_flat_type var tx -> exprf tC) :
exprf tC
| Pair {tx} (ex : exprf tx) {ty} (ey : exprf ty) : exprf (Prod tx ty).
Global Arguments Var {_} _.
Global Arguments LetIn {_} _ {_} _.
Global Arguments Pair {_} _ {_} _.
Notation "T x [1] = { A } ; 'return' ( b0 , b1 , .. , b2 )" := (LetIn (tx:=T) A
(fun x => Pair .. (Pair b0%expr b1%expr) .. b2%expr)) : expr_scope.
Definition foo :=
  (fun x3 =>
     (LetIn (Var x3) (fun x18 : var TZ
                      => (Pair (Var x18) (Var x18))))).
Print foo.
