let rec map_types f (gen:'a list) tm = match tm.term with
| Unit | Bool _ | Int _ | String _ | Float _ | Encoder _ | Var _ ->
{ tm with t = f gen tm.t }
| Ref r ->
{ t = f gen tm.t ;
term = Ref (map_types f gen r) }
| Get r ->
{ t = f gen tm.t ;
term = Get (map_types f gen r) }
| Product (a,b) ->
{ t = f gen tm.t ;
term = Product (map_types f gen a, map_types f gen b) }
| Seq (a,b) ->
{ t = f gen tm.t ;
term = Seq (map_types f gen a, map_types f gen b) }
| Set (a,b) ->
{ t = f gen tm.t ;
term = Set (map_types f gen a, map_types f gen b) }
| List l ->
{ t = f gen tm.t ;
term = List (List.map (map_types f gen) l) }
| App (hd,l) ->
{ t = f gen tm.t ;
term = App (map_types f gen hd,
List.map (fun (lbl,v) -> lbl, map_types f gen v) l) }
| Fun (fv,p,v) ->
let aux = function
| (lbl,var,t,None) -> lbl, var, f gen t, None
| (lbl,var,t,Some tm) -> lbl, var, f gen t, Some (map_types f gen tm)
in
{ t = f gen tm.t ;
term = Fun (fv, List.map aux p, map_types f gen v) }
| Let l ->
let gen' = l.gen@gen in
{ t = f gen tm.t ;
term = Let { l with def = map_types f gen' l.def ;
body = map_types f gen l.body } }