now rewrite serialize_deserialize_id_nil.
Qed.
End examples.
End sexp.
Module JSON.
Module json.
Inductive t :=
| Null : t
| Bool : bool -> t
| Num : nat -> t
| String : String.string -> t
| Arr : list t -> t
| Obj : list (String.string * t) -> t.
Section json_rect.
Variable P : t -> Type.
Variable P_list : list t -> Type.
Variable P_list' : list (String.string * t) -> Type.
Hypothesis P_nil : P_list [].
Hypothesis P_cons : forall j l, P j -> P_list l -> P_list (j :: l).
Hypothesis P_nil' : P_list' [].
Hypothesis P_cons' : forall s j l, P j -> P_list' l -> P_list' ((s, j) :: l).
Hypothesis P_null : P Null.
Hypothesis P_bool : forall b, P (Bool b).
Hypothesis P_num : forall n, P (Num n).
Hypothesis P_string : forall s, P (String s).
Hypothesis P_arr : forall l, P_list l -> P (Arr l).
Hypothesis P_obj : forall l, P_list' l -> P (Obj l).
Fixpoint json_rect (j : t) : P j :=
let fix go_list (l : list t) : P_list l :=
match l with
| [] => P_nil
| j :: l => P_cons (json_rect j) (go_list l)
end in
let fix go_list' (l : list (String.string * t)) : P_list' l :=
match l with
| [] => P_nil'
| (s, j) :: l => P_cons' s (json_rect j) (go_list' l)
end in
match j with
| Null => P_null
| Bool b => P_bool b
| Num n => P_num n
| String s => P_string s
| Arr l => P_arr (go_list l)
| Obj l => P_obj (go_list' l)
end.
End json_rect.
(* Setting P_list := List.Forall P is a reasonable default. *)
Section json_ind.
Variable P : t -> Prop.
Hypothesis P_null : P Null.
Hypothesis P_bool : forall b, P (Bool b).
Hypothesis P_num : forall n, P (Num n).
Hypothesis P_string : forall s, P (String s).
Hypothesis P_arr : forall l, List.Forall P l -> P (Arr l).
Hypothesis P_obj : forall l, List.Forall (fun s => P (snd s)) l -> P (Obj l).
Definition json_ind (j : t) : P j :=
json_rect P (List.Forall P)
(List.Forall (fun s => P (snd s)))
(List.Forall_nil _) (fun j l Pt Pl => List.Forall_cons j Pt Pl)
(List.Forall_nil _)
(fun s j l Pj Pt => List.Forall_cons (s, j) Pj Pt)
P_null
P_bool
P_num
P_string
P_arr
P_obj
j.
End json_ind.
End json.
Module tag.
Inductive t :=
| Null : t
| Bool : bool -> t
| Num : nat -> t
| Str : String.string -> t
| Arr : t
| Obj : t.
(* tag serializer *)
Definition tag_serialize (t : t) : IOStreamWriter.t :=
match t with
| Null => serialize x00
| Bool b => IOStreamWriter.append (fun _ => serialize x01)
(fun _ => serialize b)
| Num n => IOStreamWriter.append (fun _ => serialize x02)
(fun _ => serialize n)
| Str s => IOStreamWriter.append (fun _ => serialize x03)
(fun _ => serialize s)
| Arr => serialize x04
| Obj => serialize x05
end.
Definition tag_deserialize : ByteListReader.t t :=
tag <- deserialize ;;
match tag with
| x00 => ByteListReader.ret Null
| x01 => Bool <$> deserialize
| x02 => Num <$> deserialize
| x03 => Str <$> deserialize
| x04 => ByteListReader.ret Arr
| x05 => ByteListReader.ret Obj
| _ => ByteListReader.error
end.

Lemma tag_serialize_deserialize_id :
serialize_deserialize_id_spec tag_serialize tag_deserialize.