Module Type ADR_VAL.
Parameter address : Type.
Parameter some_address:address.
(* Validity of traces.  The "valid" predicate ensures that related addresses don't get split apart from each other.  *)
Parameter kind: Type.
End ADR_VAL.
Inductive TypeTree: Type :=
| ConstType: Type -> TypeTree
| Mpred: TypeTree
| DependentType: nat -> TypeTree
| ProdType: TypeTree -> TypeTree -> TypeTree
| ArrowType: TypeTree -> TypeTree -> TypeTree
| SigType: forall (I : Type), (I -> TypeTree) -> TypeTree
| PiType: forall (I : Type), (I -> TypeTree) -> TypeTree
| ListType: TypeTree -> TypeTree.
Definition dependent_type_functor_rec (ts: list Type): TypeTree -> functor :=
fix dtfr (T: TypeTree): functor :=
match T with
| ConstType A => fconst A
| Mpred => fidentity
| DependentType n => fconst (nth n ts unit)
| ProdType T1 T2 => fpair (dtfr T1) (dtfr T2)
| ArrowType T1 T2 => ffunc (dtfr T1) (dtfr T2)
| SigType _ f => fsig (fun i => dtfr (f i))
| PiType _ f => fpi (fun i => dtfr (f i))
| ListType T => flist (dtfr T)
end.
Opaque dependent_type_functor_rec.
Definition dependent_type_function_rec (ts: list Type) (mpred': Type): TypeTree -> Type :=
fix dtfr (T: TypeTree): Type :=
match T with
| ConstType A => A
| Mpred => mpred'
| DependentType n => nth n ts unit
| ProdType T1 T2 => (dtfr T1 * dtfr T2)%type
| ArrowType T1 T2 => dtfr T1 -> dtfr T2
| SigType A f => sigT (fun a => dtfr (f a))
| PiType A f => forall a, dtfr (f a)
| ListType T => list (dtfr T)
end.
Definition fpreds: functor :=
fsig (fun T: TypeTree =>
fpi (fun ts: list Type => dependent_type_functor_rec ts T)).

Lemma lower_join_inv : forall {A} {J: Join A} a b c, lower_join J a b c <->
match a, b, c with
| Some a, Some b, Some c => join a b c
| Some a, None, Some c | None, Some a, Some c => a = c
| None, None, None => True
| _, _, _ => False
end.