let e_app f args = 
  if not (simpl()) then Tapp(f,args)
  else
    match f , args with
      | "add_int" , [ Tconst (ConstInt a) ; Tconst (ConstInt b) ] ->
          i_compute Big_int.add_big_int a b
      | "sub_int" , [ Tconst (ConstInt a) ; Tconst (ConstInt b) ] ->
          i_compute Big_int.sub_big_int a b
      | "mul_int" , [ Tconst (ConstInt a) ; Tconst (ConstInt b) ] ->
          i_compute Big_int.mult_big_int a b
      | "add_int" , [ Tconst (ConstInt "0") ; x ] -> x
      | "add_int" , [ x ; Tconst (ConstInt "0") ] -> x
      | "sub_int" , [ x ; Tconst (ConstInt "0") ] -> x
      | "mul_int" , [ Tconst (ConstInt "1") ; x ] -> x
      | "mul_int" , [ x ; Tconst (ConstInt "1") ] -> x
      | "mul_int" , [ (Tconst (ConstInt "0")) as z ; _ ] -> z
      | "mul_int" , [ _ ; (Tconst (ConstInt "0")) as z ] -> z
      | "add_int" , [ b ; Tapp("sub_int",[a;c]) ] when bad_eq_terms b c -> a ;
      | "add_int" , [ Tapp("sub_int",[a;b]) ; c ] when bad_eq_terms b c -> a
      | "sub_int" , [ Tapp("add_int",[a;b]) ; c ] when bad_eq_terms b c -> a
      | "encode" , [ Tapp("decode" , [ a ; fmt ]) ; fmt' ] when bad_eq_terms fmt fmt' -> a
      | "decode" , [ Tapp("encode" , [ a ; fmt ]) ; fmt' ] when bad_eq_terms fmt fmt' -> a
      | "access" , [ Tapp("update" , [ _ ; k ; v ]) ; k' ] when bad_eq_terms k k' -> v
      | _ -> Tapp (f, args)