Definition CostModel := forall (A B : Type), (A -> B) -> nat -> Prop.Class constant_cost_relation(cost : CostModel) :={

  constant_cost_const : 
  forall (A B : Type)(b : B),
    cost _ _ (fun (_ : A) => b) 0;

  constant_cost_pair_args : 
  forall (A B C : Type)
    (f : A -> B -> C) c,
    cost _ _ (fun p => f (fst p) (snd p)) c ->
    exists c1 c2,
    cost _ _ f c1 /\ (forall a, cost _ _ (f a) c2) /\ c1 + c2 <= c;

  constant_cost_unpair_args : 
  forall (A B C : Type)
    (f : (A * B) -> C) c,
    cost _ _ f c ->
    cost _ _ (fun a b => f (a, b)) 0 /\
    (forall a, cost _ _ (fun b => f (a, b)) c);

  constant_cost_compose : 
  forall (A B C : Type)
    (f1 : A -> B)(f2 : A -> B -> C) c1 c2 c3,
    cost _ _ f1 c1 ->
    cost _ _ f2 c2 -> 
    (forall a, cost _ _ (f2 a) c3) -> 
    cost _ _ (fun a => f2 a (f1 a)) (c1 + c2 + c3);

  constant_cost_bind :
    forall (Z : Type)(A B : Set)(f1 : Z -> Comp A) (f2 : Z -> A -> Comp B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      (forall z, cost _ _ (f2 z) c3) -> 
      cost _ _ (fun a => Bind (f1 a) (f2 a)) (c1 + c2 + c3);

  constant_cost_ret :
    forall (A : Set)(eqd : eq_dec A),
      cost _ _ (@Ret A eqd) 0;

  constant_cost_le :
    forall A B (f : A -> B) c1 c2,
      cost _ _ f c1 ->
      c1 <= c2 ->
      cost _ _ f c2;

  constant_cost_fst : 
    forall (A B : Type),
      cost _ _ (@fst A B) 0;

  constant_cost_snd : 
    forall (A B : Type),
      cost _ _ (@snd A B) 0;

  constant_cost_pair_1 : 
    forall (A B : Type),
      cost _ _ (@pair A B) 0;

  constant_cost_pair_2 : 
    forall (A B : Type) a,
      cost _ _ (@pair A B a) 0;

  constant_cost_pair : 
    forall (A B : Type),
      cost _ _ (fun p => @pair A B (fst p) (snd p)) 0;
  
  constant_cost_eqb_bool : 
    cost _ _ (fun p => @eqb bool _ (fst p) (snd p)) 1;

  constant_cost_bvxor : 
    forall eta, 
      cost _ _ (fun p => BVxor eta (fst p) (snd p)) eta;

  constant_cost_firstn : 
    forall k (A : Type),
      cost _ _ (@firstn A k) k;
  
  constant_cost_skipn : 
    forall k (A : Type),
      cost _ _ (@skipn A k) k;

  constant_cost_tl : 
    forall (A : Type),
      cost _ _ (@tl A) 1;
  
  constant_cost_hd : 
    forall (A : Type)(a : A),
      cost _ _ (hd a) 1;

  constant_cost_if_bool_f :
    forall (A B : Type)(f1 : A -> bool)(f2 f3 : A -> B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      cost _ _ f3 c3 ->
      cost _ _ (fun a => if (f1 a) then (f2 a) else (f3 a)) (c1 + c2 + c3)

}.Class constant_cost_relation(cost : CostModel) :={

  constant_cost_const : 
  forall (A B : Type)(b : B),
    cost _ _ (fun (_ : A) => b) 0;

  constant_cost_pair_args : 
  forall (A B C : Type)
    (f : A -> B -> C) c,
    cost _ _ (fun p => f (fst p) (snd p)) c ->
    exists c1 c2,
    cost _ _ f c1 /\ (forall a, cost _ _ (f a) c2) /\ c1 + c2 <= c;

  constant_cost_unpair_args : 
  forall (A B C : Type)
    (f : (A * B) -> C) c,
    cost _ _ f c ->
    cost _ _ (fun a b => f (a, b)) 0 /\
    (forall a, cost _ _ (fun b => f (a, b)) c);

  constant_cost_compose : 
  forall (A B C : Type)
    (f1 : A -> B)(f2 : A -> B -> C) c1 c2 c3,
    cost _ _ f1 c1 ->
    cost _ _ f2 c2 -> 
    (forall a, cost _ _ (f2 a) c3) -> 
    cost _ _ (fun a => f2 a (f1 a)) (c1 + c2 + c3);

  constant_cost_bind :
    forall (Z : Type)(A B : Set)(f1 : Z -> Comp A) (f2 : Z -> A -> Comp B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      (forall z, cost _ _ (f2 z) c3) -> 
      cost _ _ (fun a => Bind (f1 a) (f2 a)) (c1 + c2 + c3);

  constant_cost_ret :
    forall (A : Set)(eqd : eq_dec A),
      cost _ _ (@Ret A eqd) 0;

  constant_cost_le :
    forall A B (f : A -> B) c1 c2,
      cost _ _ f c1 ->
      c1 <= c2 ->
      cost _ _ f c2;

  constant_cost_fst : 
    forall (A B : Type),
      cost _ _ (@fst A B) 0;

  constant_cost_snd : 
    forall (A B : Type),
      cost _ _ (@snd A B) 0;

  constant_cost_pair_1 : 
    forall (A B : Type),
      cost _ _ (@pair A B) 0;

  constant_cost_pair_2 : 
    forall (A B : Type) a,
      cost _ _ (@pair A B a) 0;

  constant_cost_pair : 
    forall (A B : Type),
      cost _ _ (fun p => @pair A B (fst p) (snd p)) 0;
  
  constant_cost_eqb_bool : 
    cost _ _ (fun p => @eqb bool _ (fst p) (snd p)) 1;

  constant_cost_bvxor : 
    forall eta, 
      cost _ _ (fun p => BVxor eta (fst p) (snd p)) eta;

  constant_cost_firstn : 
    forall k (A : Type),
      cost _ _ (@firstn A k) k;
  
  constant_cost_skipn : 
    forall k (A : Type),
      cost _ _ (@skipn A k) k;

  constant_cost_tl : 
    forall (A : Type),
      cost _ _ (@tl A) 1;
  
  constant_cost_hd : 
    forall (A : Type)(a : A),
      cost _ _ (hd a) 1;

  constant_cost_if_bool_f :
    forall (A B : Type)(f1 : A -> bool)(f2 f3 : A -> B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      cost _ _ f3 c3 ->
      cost _ _ (fun a => if (f1 a) then (f2 a) else (f3 a)) (c1 + c2 + c3)

}.Class constant_cost_relation(cost : CostModel) :={

  constant_cost_const : 
  forall (A B : Type)(b : B),
    cost _ _ (fun (_ : A) => b) 0;

  constant_cost_pair_args : 
  forall (A B C : Type)
    (f : A -> B -> C) c,
    cost _ _ (fun p => f (fst p) (snd p)) c ->
    exists c1 c2,
    cost _ _ f c1 /\ (forall a, cost _ _ (f a) c2) /\ c1 + c2 <= c;

  constant_cost_unpair_args : 
  forall (A B C : Type)
    (f : (A * B) -> C) c,
    cost _ _ f c ->
    cost _ _ (fun a b => f (a, b)) 0 /\
    (forall a, cost _ _ (fun b => f (a, b)) c);

  constant_cost_compose : 
  forall (A B C : Type)
    (f1 : A -> B)(f2 : A -> B -> C) c1 c2 c3,
    cost _ _ f1 c1 ->
    cost _ _ f2 c2 -> 
    (forall a, cost _ _ (f2 a) c3) -> 
    cost _ _ (fun a => f2 a (f1 a)) (c1 + c2 + c3);

  constant_cost_bind :
    forall (Z : Type)(A B : Set)(f1 : Z -> Comp A) (f2 : Z -> A -> Comp B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      (forall z, cost _ _ (f2 z) c3) -> 
      cost _ _ (fun a => Bind (f1 a) (f2 a)) (c1 + c2 + c3);

  constant_cost_ret :
    forall (A : Set)(eqd : eq_dec A),
      cost _ _ (@Ret A eqd) 0;

  constant_cost_le :
    forall A B (f : A -> B) c1 c2,
      cost _ _ f c1 ->
      c1 <= c2 ->
      cost _ _ f c2;

  constant_cost_fst : 
    forall (A B : Type),
      cost _ _ (@fst A B) 0;

  constant_cost_snd : 
    forall (A B : Type),
      cost _ _ (@snd A B) 0;

  constant_cost_pair_1 : 
    forall (A B : Type),
      cost _ _ (@pair A B) 0;

  constant_cost_pair_2 : 
    forall (A B : Type) a,
      cost _ _ (@pair A B a) 0;

  constant_cost_pair : 
    forall (A B : Type),
      cost _ _ (fun p => @pair A B (fst p) (snd p)) 0;
  
  constant_cost_eqb_bool : 
    cost _ _ (fun p => @eqb bool _ (fst p) (snd p)) 1;

  constant_cost_bvxor : 
    forall eta, 
      cost _ _ (fun p => BVxor eta (fst p) (snd p)) eta;

  constant_cost_firstn : 
    forall k (A : Type),
      cost _ _ (@firstn A k) k;
  
  constant_cost_skipn : 
    forall k (A : Type),
      cost _ _ (@skipn A k) k;

  constant_cost_tl : 
    forall (A : Type),
      cost _ _ (@tl A) 1;
  
  constant_cost_hd : 
    forall (A : Type)(a : A),
      cost _ _ (hd a) 1;

  constant_cost_if_bool_f :
    forall (A B : Type)(f1 : A -> bool)(f2 f3 : A -> B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      cost _ _ f3 c3 ->
      cost _ _ (fun a => if (f1 a) then (f2 a) else (f3 a)) (c1 + c2 + c3)

}.Class constant_cost_relation(cost : CostModel) :={

  constant_cost_const : 
  forall (A B : Type)(b : B),
    cost _ _ (fun (_ : A) => b) 0;

  constant_cost_pair_args : 
  forall (A B C : Type)
    (f : A -> B -> C) c,
    cost _ _ (fun p => f (fst p) (snd p)) c ->
    exists c1 c2,
    cost _ _ f c1 /\ (forall a, cost _ _ (f a) c2) /\ c1 + c2 <= c;

  constant_cost_unpair_args : 
  forall (A B C : Type)
    (f : (A * B) -> C) c,
    cost _ _ f c ->
    cost _ _ (fun a b => f (a, b)) 0 /\
    (forall a, cost _ _ (fun b => f (a, b)) c);

  constant_cost_compose : 
  forall (A B C : Type)
    (f1 : A -> B)(f2 : A -> B -> C) c1 c2 c3,
    cost _ _ f1 c1 ->
    cost _ _ f2 c2 -> 
    (forall a, cost _ _ (f2 a) c3) -> 
    cost _ _ (fun a => f2 a (f1 a)) (c1 + c2 + c3);

  constant_cost_bind :
    forall (Z : Type)(A B : Set)(f1 : Z -> Comp A) (f2 : Z -> A -> Comp B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      (forall z, cost _ _ (f2 z) c3) -> 
      cost _ _ (fun a => Bind (f1 a) (f2 a)) (c1 + c2 + c3);

  constant_cost_ret :
    forall (A : Set)(eqd : eq_dec A),
      cost _ _ (@Ret A eqd) 0;

  constant_cost_le :
    forall A B (f : A -> B) c1 c2,
      cost _ _ f c1 ->
      c1 <= c2 ->
      cost _ _ f c2;

  constant_cost_fst : 
    forall (A B : Type),
      cost _ _ (@fst A B) 0;

  constant_cost_snd : 
    forall (A B : Type),
      cost _ _ (@snd A B) 0;

  constant_cost_pair_1 : 
    forall (A B : Type),
      cost _ _ (@pair A B) 0;

  constant_cost_pair_2 : 
    forall (A B : Type) a,
      cost _ _ (@pair A B a) 0;

  constant_cost_pair : 
    forall (A B : Type),
      cost _ _ (fun p => @pair A B (fst p) (snd p)) 0;
  
  constant_cost_eqb_bool : 
    cost _ _ (fun p => @eqb bool _ (fst p) (snd p)) 1;

  constant_cost_bvxor : 
    forall eta, 
      cost _ _ (fun p => BVxor eta (fst p) (snd p)) eta;

  constant_cost_firstn : 
    forall k (A : Type),
      cost _ _ (@firstn A k) k;
  
  constant_cost_skipn : 
    forall k (A : Type),
      cost _ _ (@skipn A k) k;

  constant_cost_tl : 
    forall (A : Type),
      cost _ _ (@tl A) 1;
  
  constant_cost_hd : 
    forall (A : Type)(a : A),
      cost _ _ (hd a) 1;

  constant_cost_if_bool_f :
    forall (A B : Type)(f1 : A -> bool)(f2 f3 : A -> B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      cost _ _ f3 c3 ->
      cost _ _ (fun a => if (f1 a) then (f2 a) else (f3 a)) (c1 + c2 + c3)

}.Class constant_cost_relation(cost : CostModel) :={

  constant_cost_const : 
  forall (A B : Type)(b : B),
    cost _ _ (fun (_ : A) => b) 0;

  constant_cost_pair_args : 
  forall (A B C : Type)
    (f : A -> B -> C) c,
    cost _ _ (fun p => f (fst p) (snd p)) c ->
    exists c1 c2,
    cost _ _ f c1 /\ (forall a, cost _ _ (f a) c2) /\ c1 + c2 <= c;

  constant_cost_unpair_args : 
  forall (A B C : Type)
    (f : (A * B) -> C) c,
    cost _ _ f c ->
    cost _ _ (fun a b => f (a, b)) 0 /\
    (forall a, cost _ _ (fun b => f (a, b)) c);

  constant_cost_compose : 
  forall (A B C : Type)
    (f1 : A -> B)(f2 : A -> B -> C) c1 c2 c3,
    cost _ _ f1 c1 ->
    cost _ _ f2 c2 -> 
    (forall a, cost _ _ (f2 a) c3) -> 
    cost _ _ (fun a => f2 a (f1 a)) (c1 + c2 + c3);

  constant_cost_bind :
    forall (Z : Type)(A B : Set)(f1 : Z -> Comp A) (f2 : Z -> A -> Comp B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      (forall z, cost _ _ (f2 z) c3) -> 
      cost _ _ (fun a => Bind (f1 a) (f2 a)) (c1 + c2 + c3);

  constant_cost_ret :
    forall (A : Set)(eqd : eq_dec A),
      cost _ _ (@Ret A eqd) 0;

  constant_cost_le :
    forall A B (f : A -> B) c1 c2,
      cost _ _ f c1 ->
      c1 <= c2 ->
      cost _ _ f c2;

  constant_cost_fst : 
    forall (A B : Type),
      cost _ _ (@fst A B) 0;

  constant_cost_snd : 
    forall (A B : Type),
      cost _ _ (@snd A B) 0;

  constant_cost_pair_1 : 
    forall (A B : Type),
      cost _ _ (@pair A B) 0;

  constant_cost_pair_2 : 
    forall (A B : Type) a,
      cost _ _ (@pair A B a) 0;

  constant_cost_pair : 
    forall (A B : Type),
      cost _ _ (fun p => @pair A B (fst p) (snd p)) 0;
  
  constant_cost_eqb_bool : 
    cost _ _ (fun p => @eqb bool _ (fst p) (snd p)) 1;

  constant_cost_bvxor : 
    forall eta, 
      cost _ _ (fun p => BVxor eta (fst p) (snd p)) eta;

  constant_cost_firstn : 
    forall k (A : Type),
      cost _ _ (@firstn A k) k;
  
  constant_cost_skipn : 
    forall k (A : Type),
      cost _ _ (@skipn A k) k;

  constant_cost_tl : 
    forall (A : Type),
      cost _ _ (@tl A) 1;
  
  constant_cost_hd : 
    forall (A : Type)(a : A),
      cost _ _ (hd a) 1;

  constant_cost_if_bool_f :
    forall (A B : Type)(f1 : A -> bool)(f2 f3 : A -> B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      cost _ _ f3 c3 ->
      cost _ _ (fun a => if (f1 a) then (f2 a) else (f3 a)) (c1 + c2 + c3)

}.Class constant_cost_relation(cost : CostModel) :={

  constant_cost_const : 
  forall (A B : Type)(b : B),
    cost _ _ (fun (_ : A) => b) 0;

  constant_cost_pair_args : 
  forall (A B C : Type)
    (f : A -> B -> C) c,
    cost _ _ (fun p => f (fst p) (snd p)) c ->
    exists c1 c2,
    cost _ _ f c1 /\ (forall a, cost _ _ (f a) c2) /\ c1 + c2 <= c;

  constant_cost_unpair_args : 
  forall (A B C : Type)
    (f : (A * B) -> C) c,
    cost _ _ f c ->
    cost _ _ (fun a b => f (a, b)) 0 /\
    (forall a, cost _ _ (fun b => f (a, b)) c);

  constant_cost_compose : 
  forall (A B C : Type)
    (f1 : A -> B)(f2 : A -> B -> C) c1 c2 c3,
    cost _ _ f1 c1 ->
    cost _ _ f2 c2 -> 
    (forall a, cost _ _ (f2 a) c3) -> 
    cost _ _ (fun a => f2 a (f1 a)) (c1 + c2 + c3);

  constant_cost_bind :
    forall (Z : Type)(A B : Set)(f1 : Z -> Comp A) (f2 : Z -> A -> Comp B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      (forall z, cost _ _ (f2 z) c3) -> 
      cost _ _ (fun a => Bind (f1 a) (f2 a)) (c1 + c2 + c3);

  constant_cost_ret :
    forall (A : Set)(eqd : eq_dec A),
      cost _ _ (@Ret A eqd) 0;

  constant_cost_le :
    forall A B (f : A -> B) c1 c2,
      cost _ _ f c1 ->
      c1 <= c2 ->
      cost _ _ f c2;

  constant_cost_fst : 
    forall (A B : Type),
      cost _ _ (@fst A B) 0;

  constant_cost_snd : 
    forall (A B : Type),
      cost _ _ (@snd A B) 0;

  constant_cost_pair_1 : 
    forall (A B : Type),
      cost _ _ (@pair A B) 0;

  constant_cost_pair_2 : 
    forall (A B : Type) a,
      cost _ _ (@pair A B a) 0;

  constant_cost_pair : 
    forall (A B : Type),
      cost _ _ (fun p => @pair A B (fst p) (snd p)) 0;
  
  constant_cost_eqb_bool : 
    cost _ _ (fun p => @eqb bool _ (fst p) (snd p)) 1;

  constant_cost_bvxor : 
    forall eta, 
      cost _ _ (fun p => BVxor eta (fst p) (snd p)) eta;

  constant_cost_firstn : 
    forall k (A : Type),
      cost _ _ (@firstn A k) k;
  
  constant_cost_skipn : 
    forall k (A : Type),
      cost _ _ (@skipn A k) k;

  constant_cost_tl : 
    forall (A : Type),
      cost _ _ (@tl A) 1;
  
  constant_cost_hd : 
    forall (A : Type)(a : A),
      cost _ _ (hd a) 1;

  constant_cost_if_bool_f :
    forall (A B : Type)(f1 : A -> bool)(f2 f3 : A -> B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      cost _ _ f3 c3 ->
      cost _ _ (fun a => if (f1 a) then (f2 a) else (f3 a)) (c1 + c2 + c3)

}.Class constant_cost_relation(cost : CostModel) :={

  constant_cost_const : 
  forall (A B : Type)(b : B),
    cost _ _ (fun (_ : A) => b) 0;

  constant_cost_pair_args : 
  forall (A B C : Type)
    (f : A -> B -> C) c,
    cost _ _ (fun p => f (fst p) (snd p)) c ->
    exists c1 c2,
    cost _ _ f c1 /\ (forall a, cost _ _ (f a) c2) /\ c1 + c2 <= c;

  constant_cost_unpair_args : 
  forall (A B C : Type)
    (f : (A * B) -> C) c,
    cost _ _ f c ->
    cost _ _ (fun a b => f (a, b)) 0 /\
    (forall a, cost _ _ (fun b => f (a, b)) c);

  constant_cost_compose : 
  forall (A B C : Type)
    (f1 : A -> B)(f2 : A -> B -> C) c1 c2 c3,
    cost _ _ f1 c1 ->
    cost _ _ f2 c2 -> 
    (forall a, cost _ _ (f2 a) c3) -> 
    cost _ _ (fun a => f2 a (f1 a)) (c1 + c2 + c3);

  constant_cost_bind :
    forall (Z : Type)(A B : Set)(f1 : Z -> Comp A) (f2 : Z -> A -> Comp B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      (forall z, cost _ _ (f2 z) c3) -> 
      cost _ _ (fun a => Bind (f1 a) (f2 a)) (c1 + c2 + c3);

  constant_cost_ret :
    forall (A : Set)(eqd : eq_dec A),
      cost _ _ (@Ret A eqd) 0;

  constant_cost_le :
    forall A B (f : A -> B) c1 c2,
      cost _ _ f c1 ->
      c1 <= c2 ->
      cost _ _ f c2;

  constant_cost_fst : 
    forall (A B : Type),
      cost _ _ (@fst A B) 0;

  constant_cost_snd : 
    forall (A B : Type),
      cost _ _ (@snd A B) 0;

  constant_cost_pair_1 : 
    forall (A B : Type),
      cost _ _ (@pair A B) 0;

  constant_cost_pair_2 : 
    forall (A B : Type) a,
      cost _ _ (@pair A B a) 0;

  constant_cost_pair : 
    forall (A B : Type),
      cost _ _ (fun p => @pair A B (fst p) (snd p)) 0;
  
  constant_cost_eqb_bool : 
    cost _ _ (fun p => @eqb bool _ (fst p) (snd p)) 1;

  constant_cost_bvxor : 
    forall eta, 
      cost _ _ (fun p => BVxor eta (fst p) (snd p)) eta;

  constant_cost_firstn : 
    forall k (A : Type),
      cost _ _ (@firstn A k) k;
  
  constant_cost_skipn : 
    forall k (A : Type),
      cost _ _ (@skipn A k) k;

  constant_cost_tl : 
    forall (A : Type),
      cost _ _ (@tl A) 1;
  
  constant_cost_hd : 
    forall (A : Type)(a : A),
      cost _ _ (hd a) 1;

  constant_cost_if_bool_f :
    forall (A B : Type)(f1 : A -> bool)(f2 f3 : A -> B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      cost _ _ f3 c3 ->
      cost _ _ (fun a => if (f1 a) then (f2 a) else (f3 a)) (c1 + c2 + c3)

}.Class constant_cost_relation(cost : CostModel) :={

  constant_cost_const : 
  forall (A B : Type)(b : B),
    cost _ _ (fun (_ : A) => b) 0;

  constant_cost_pair_args : 
  forall (A B C : Type)
    (f : A -> B -> C) c,
    cost _ _ (fun p => f (fst p) (snd p)) c ->
    exists c1 c2,
    cost _ _ f c1 /\ (forall a, cost _ _ (f a) c2) /\ c1 + c2 <= c;

  constant_cost_unpair_args : 
  forall (A B C : Type)
    (f : (A * B) -> C) c,
    cost _ _ f c ->
    cost _ _ (fun a b => f (a, b)) 0 /\
    (forall a, cost _ _ (fun b => f (a, b)) c);

  constant_cost_compose : 
  forall (A B C : Type)
    (f1 : A -> B)(f2 : A -> B -> C) c1 c2 c3,
    cost _ _ f1 c1 ->
    cost _ _ f2 c2 -> 
    (forall a, cost _ _ (f2 a) c3) -> 
    cost _ _ (fun a => f2 a (f1 a)) (c1 + c2 + c3);

  constant_cost_bind :
    forall (Z : Type)(A B : Set)(f1 : Z -> Comp A) (f2 : Z -> A -> Comp B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      (forall z, cost _ _ (f2 z) c3) -> 
      cost _ _ (fun a => Bind (f1 a) (f2 a)) (c1 + c2 + c3);

  constant_cost_ret :
    forall (A : Set)(eqd : eq_dec A),
      cost _ _ (@Ret A eqd) 0;

  constant_cost_le :
    forall A B (f : A -> B) c1 c2,
      cost _ _ f c1 ->
      c1 <= c2 ->
      cost _ _ f c2;

  constant_cost_fst : 
    forall (A B : Type),
      cost _ _ (@fst A B) 0;

  constant_cost_snd : 
    forall (A B : Type),
      cost _ _ (@snd A B) 0;

  constant_cost_pair_1 : 
    forall (A B : Type),
      cost _ _ (@pair A B) 0;

  constant_cost_pair_2 : 
    forall (A B : Type) a,
      cost _ _ (@pair A B a) 0;

  constant_cost_pair : 
    forall (A B : Type),
      cost _ _ (fun p => @pair A B (fst p) (snd p)) 0;
  
  constant_cost_eqb_bool : 
    cost _ _ (fun p => @eqb bool _ (fst p) (snd p)) 1;

  constant_cost_bvxor : 
    forall eta, 
      cost _ _ (fun p => BVxor eta (fst p) (snd p)) eta;

  constant_cost_firstn : 
    forall k (A : Type),
      cost _ _ (@firstn A k) k;
  
  constant_cost_skipn : 
    forall k (A : Type),
      cost _ _ (@skipn A k) k;

  constant_cost_tl : 
    forall (A : Type),
      cost _ _ (@tl A) 1;
  
  constant_cost_hd : 
    forall (A : Type)(a : A),
      cost _ _ (hd a) 1;

  constant_cost_if_bool_f :
    forall (A B : Type)(f1 : A -> bool)(f2 f3 : A -> B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      cost _ _ f3 c3 ->
      cost _ _ (fun a => if (f1 a) then (f2 a) else (f3 a)) (c1 + c2 + c3)

}.Class constant_cost_relation(cost : CostModel) :={

  constant_cost_const : 
  forall (A B : Type)(b : B),
    cost _ _ (fun (_ : A) => b) 0;

  constant_cost_pair_args : 
  forall (A B C : Type)
    (f : A -> B -> C) c,
    cost _ _ (fun p => f (fst p) (snd p)) c ->
    exists c1 c2,
    cost _ _ f c1 /\ (forall a, cost _ _ (f a) c2) /\ c1 + c2 <= c;

  constant_cost_unpair_args : 
  forall (A B C : Type)
    (f : (A * B) -> C) c,
    cost _ _ f c ->
    cost _ _ (fun a b => f (a, b)) 0 /\
    (forall a, cost _ _ (fun b => f (a, b)) c);

  constant_cost_compose : 
  forall (A B C : Type)
    (f1 : A -> B)(f2 : A -> B -> C) c1 c2 c3,
    cost _ _ f1 c1 ->
    cost _ _ f2 c2 -> 
    (forall a, cost _ _ (f2 a) c3) -> 
    cost _ _ (fun a => f2 a (f1 a)) (c1 + c2 + c3);

  constant_cost_bind :
    forall (Z : Type)(A B : Set)(f1 : Z -> Comp A) (f2 : Z -> A -> Comp B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      (forall z, cost _ _ (f2 z) c3) -> 
      cost _ _ (fun a => Bind (f1 a) (f2 a)) (c1 + c2 + c3);

  constant_cost_ret :
    forall (A : Set)(eqd : eq_dec A),
      cost _ _ (@Ret A eqd) 0;

  constant_cost_le :
    forall A B (f : A -> B) c1 c2,
      cost _ _ f c1 ->
      c1 <= c2 ->
      cost _ _ f c2;

  constant_cost_fst : 
    forall (A B : Type),
      cost _ _ (@fst A B) 0;

  constant_cost_snd : 
    forall (A B : Type),
      cost _ _ (@snd A B) 0;

  constant_cost_pair_1 : 
    forall (A B : Type),
      cost _ _ (@pair A B) 0;

  constant_cost_pair_2 : 
    forall (A B : Type) a,
      cost _ _ (@pair A B a) 0;

  constant_cost_pair : 
    forall (A B : Type),
      cost _ _ (fun p => @pair A B (fst p) (snd p)) 0;
  
  constant_cost_eqb_bool : 
    cost _ _ (fun p => @eqb bool _ (fst p) (snd p)) 1;

  constant_cost_bvxor : 
    forall eta, 
      cost _ _ (fun p => BVxor eta (fst p) (snd p)) eta;

  constant_cost_firstn : 
    forall k (A : Type),
      cost _ _ (@firstn A k) k;
  
  constant_cost_skipn : 
    forall k (A : Type),
      cost _ _ (@skipn A k) k;

  constant_cost_tl : 
    forall (A : Type),
      cost _ _ (@tl A) 1;
  
  constant_cost_hd : 
    forall (A : Type)(a : A),
      cost _ _ (hd a) 1;

  constant_cost_if_bool_f :
    forall (A B : Type)(f1 : A -> bool)(f2 f3 : A -> B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      cost _ _ f3 c3 ->
      cost _ _ (fun a => if (f1 a) then (f2 a) else (f3 a)) (c1 + c2 + c3)

}.Class constant_cost_relation(cost : CostModel) :={

  constant_cost_const : 
  forall (A B : Type)(b : B),
    cost _ _ (fun (_ : A) => b) 0;

  constant_cost_pair_args : 
  forall (A B C : Type)
    (f : A -> B -> C) c,
    cost _ _ (fun p => f (fst p) (snd p)) c ->
    exists c1 c2,
    cost _ _ f c1 /\ (forall a, cost _ _ (f a) c2) /\ c1 + c2 <= c;

  constant_cost_unpair_args : 
  forall (A B C : Type)
    (f : (A * B) -> C) c,
    cost _ _ f c ->
    cost _ _ (fun a b => f (a, b)) 0 /\
    (forall a, cost _ _ (fun b => f (a, b)) c);

  constant_cost_compose : 
  forall (A B C : Type)
    (f1 : A -> B)(f2 : A -> B -> C) c1 c2 c3,
    cost _ _ f1 c1 ->
    cost _ _ f2 c2 -> 
    (forall a, cost _ _ (f2 a) c3) -> 
    cost _ _ (fun a => f2 a (f1 a)) (c1 + c2 + c3);

  constant_cost_bind :
    forall (Z : Type)(A B : Set)(f1 : Z -> Comp A) (f2 : Z -> A -> Comp B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      (forall z, cost _ _ (f2 z) c3) -> 
      cost _ _ (fun a => Bind (f1 a) (f2 a)) (c1 + c2 + c3);

  constant_cost_ret :
    forall (A : Set)(eqd : eq_dec A),
      cost _ _ (@Ret A eqd) 0;

  constant_cost_le :
    forall A B (f : A -> B) c1 c2,
      cost _ _ f c1 ->
      c1 <= c2 ->
      cost _ _ f c2;

  constant_cost_fst : 
    forall (A B : Type),
      cost _ _ (@fst A B) 0;

  constant_cost_snd : 
    forall (A B : Type),
      cost _ _ (@snd A B) 0;

  constant_cost_pair_1 : 
    forall (A B : Type),
      cost _ _ (@pair A B) 0;

  constant_cost_pair_2 : 
    forall (A B : Type) a,
      cost _ _ (@pair A B a) 0;

  constant_cost_pair : 
    forall (A B : Type),
      cost _ _ (fun p => @pair A B (fst p) (snd p)) 0;
  
  constant_cost_eqb_bool : 
    cost _ _ (fun p => @eqb bool _ (fst p) (snd p)) 1;

  constant_cost_bvxor : 
    forall eta, 
      cost _ _ (fun p => BVxor eta (fst p) (snd p)) eta;

  constant_cost_firstn : 
    forall k (A : Type),
      cost _ _ (@firstn A k) k;
  
  constant_cost_skipn : 
    forall k (A : Type),
      cost _ _ (@skipn A k) k;

  constant_cost_tl : 
    forall (A : Type),
      cost _ _ (@tl A) 1;
  
  constant_cost_hd : 
    forall (A : Type)(a : A),
      cost _ _ (hd a) 1;

  constant_cost_if_bool_f :
    forall (A B : Type)(f1 : A -> bool)(f2 f3 : A -> B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      cost _ _ f3 c3 ->
      cost _ _ (fun a => if (f1 a) then (f2 a) else (f3 a)) (c1 + c2 + c3)

}.Class constant_cost_relation(cost : CostModel) :={

  constant_cost_const : 
  forall (A B : Type)(b : B),
    cost _ _ (fun (_ : A) => b) 0;

  constant_cost_pair_args : 
  forall (A B C : Type)
    (f : A -> B -> C) c,
    cost _ _ (fun p => f (fst p) (snd p)) c ->
    exists c1 c2,
    cost _ _ f c1 /\ (forall a, cost _ _ (f a) c2) /\ c1 + c2 <= c;

  constant_cost_unpair_args : 
  forall (A B C : Type)
    (f : (A * B) -> C) c,
    cost _ _ f c ->
    cost _ _ (fun a b => f (a, b)) 0 /\
    (forall a, cost _ _ (fun b => f (a, b)) c);

  constant_cost_compose : 
  forall (A B C : Type)
    (f1 : A -> B)(f2 : A -> B -> C) c1 c2 c3,
    cost _ _ f1 c1 ->
    cost _ _ f2 c2 -> 
    (forall a, cost _ _ (f2 a) c3) -> 
    cost _ _ (fun a => f2 a (f1 a)) (c1 + c2 + c3);

  constant_cost_bind :
    forall (Z : Type)(A B : Set)(f1 : Z -> Comp A) (f2 : Z -> A -> Comp B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      (forall z, cost _ _ (f2 z) c3) -> 
      cost _ _ (fun a => Bind (f1 a) (f2 a)) (c1 + c2 + c3);

  constant_cost_ret :
    forall (A : Set)(eqd : eq_dec A),
      cost _ _ (@Ret A eqd) 0;

  constant_cost_le :
    forall A B (f : A -> B) c1 c2,
      cost _ _ f c1 ->
      c1 <= c2 ->
      cost _ _ f c2;

  constant_cost_fst : 
    forall (A B : Type),
      cost _ _ (@fst A B) 0;

  constant_cost_snd : 
    forall (A B : Type),
      cost _ _ (@snd A B) 0;

  constant_cost_pair_1 : 
    forall (A B : Type),
      cost _ _ (@pair A B) 0;

  constant_cost_pair_2 : 
    forall (A B : Type) a,
      cost _ _ (@pair A B a) 0;

  constant_cost_pair : 
    forall (A B : Type),
      cost _ _ (fun p => @pair A B (fst p) (snd p)) 0;
  
  constant_cost_eqb_bool : 
    cost _ _ (fun p => @eqb bool _ (fst p) (snd p)) 1;

  constant_cost_bvxor : 
    forall eta, 
      cost _ _ (fun p => BVxor eta (fst p) (snd p)) eta;

  constant_cost_firstn : 
    forall k (A : Type),
      cost _ _ (@firstn A k) k;
  
  constant_cost_skipn : 
    forall k (A : Type),
      cost _ _ (@skipn A k) k;

  constant_cost_tl : 
    forall (A : Type),
      cost _ _ (@tl A) 1;
  
  constant_cost_hd : 
    forall (A : Type)(a : A),
      cost _ _ (hd a) 1;

  constant_cost_if_bool_f :
    forall (A B : Type)(f1 : A -> bool)(f2 f3 : A -> B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      cost _ _ f3 c3 ->
      cost _ _ (fun a => if (f1 a) then (f2 a) else (f3 a)) (c1 + c2 + c3)

}.Class constant_cost_relation(cost : CostModel) :={

  constant_cost_const : 
  forall (A B : Type)(b : B),
    cost _ _ (fun (_ : A) => b) 0;

  constant_cost_pair_args : 
  forall (A B C : Type)
    (f : A -> B -> C) c,
    cost _ _ (fun p => f (fst p) (snd p)) c ->
    exists c1 c2,
    cost _ _ f c1 /\ (forall a, cost _ _ (f a) c2) /\ c1 + c2 <= c;

  constant_cost_unpair_args : 
  forall (A B C : Type)
    (f : (A * B) -> C) c,
    cost _ _ f c ->
    cost _ _ (fun a b => f (a, b)) 0 /\
    (forall a, cost _ _ (fun b => f (a, b)) c);

  constant_cost_compose : 
  forall (A B C : Type)
    (f1 : A -> B)(f2 : A -> B -> C) c1 c2 c3,
    cost _ _ f1 c1 ->
    cost _ _ f2 c2 -> 
    (forall a, cost _ _ (f2 a) c3) -> 
    cost _ _ (fun a => f2 a (f1 a)) (c1 + c2 + c3);

  constant_cost_bind :
    forall (Z : Type)(A B : Set)(f1 : Z -> Comp A) (f2 : Z -> A -> Comp B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      (forall z, cost _ _ (f2 z) c3) -> 
      cost _ _ (fun a => Bind (f1 a) (f2 a)) (c1 + c2 + c3);

  constant_cost_ret :
    forall (A : Set)(eqd : eq_dec A),
      cost _ _ (@Ret A eqd) 0;

  constant_cost_le :
    forall A B (f : A -> B) c1 c2,
      cost _ _ f c1 ->
      c1 <= c2 ->
      cost _ _ f c2;

  constant_cost_fst : 
    forall (A B : Type),
      cost _ _ (@fst A B) 0;

  constant_cost_snd : 
    forall (A B : Type),
      cost _ _ (@snd A B) 0;

  constant_cost_pair_1 : 
    forall (A B : Type),
      cost _ _ (@pair A B) 0;

  constant_cost_pair_2 : 
    forall (A B : Type) a,
      cost _ _ (@pair A B a) 0;

  constant_cost_pair : 
    forall (A B : Type),
      cost _ _ (fun p => @pair A B (fst p) (snd p)) 0;
  
  constant_cost_eqb_bool : 
    cost _ _ (fun p => @eqb bool _ (fst p) (snd p)) 1;

  constant_cost_bvxor : 
    forall eta, 
      cost _ _ (fun p => BVxor eta (fst p) (snd p)) eta;

  constant_cost_firstn : 
    forall k (A : Type),
      cost _ _ (@firstn A k) k;
  
  constant_cost_skipn : 
    forall k (A : Type),
      cost _ _ (@skipn A k) k;

  constant_cost_tl : 
    forall (A : Type),
      cost _ _ (@tl A) 1;
  
  constant_cost_hd : 
    forall (A : Type)(a : A),
      cost _ _ (hd a) 1;

  constant_cost_if_bool_f :
    forall (A B : Type)(f1 : A -> bool)(f2 f3 : A -> B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      cost _ _ f3 c3 ->
      cost _ _ (fun a => if (f1 a) then (f2 a) else (f3 a)) (c1 + c2 + c3)

}.Class constant_cost_relation(cost : CostModel) :={

  constant_cost_const : 
  forall (A B : Type)(b : B),
    cost _ _ (fun (_ : A) => b) 0;

  constant_cost_pair_args : 
  forall (A B C : Type)
    (f : A -> B -> C) c,
    cost _ _ (fun p => f (fst p) (snd p)) c ->
    exists c1 c2,
    cost _ _ f c1 /\ (forall a, cost _ _ (f a) c2) /\ c1 + c2 <= c;

  constant_cost_unpair_args : 
  forall (A B C : Type)
    (f : (A * B) -> C) c,
    cost _ _ f c ->
    cost _ _ (fun a b => f (a, b)) 0 /\
    (forall a, cost _ _ (fun b => f (a, b)) c);

  constant_cost_compose : 
  forall (A B C : Type)
    (f1 : A -> B)(f2 : A -> B -> C) c1 c2 c3,
    cost _ _ f1 c1 ->
    cost _ _ f2 c2 -> 
    (forall a, cost _ _ (f2 a) c3) -> 
    cost _ _ (fun a => f2 a (f1 a)) (c1 + c2 + c3);

  constant_cost_bind :
    forall (Z : Type)(A B : Set)(f1 : Z -> Comp A) (f2 : Z -> A -> Comp B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      (forall z, cost _ _ (f2 z) c3) -> 
      cost _ _ (fun a => Bind (f1 a) (f2 a)) (c1 + c2 + c3);

  constant_cost_ret :
    forall (A : Set)(eqd : eq_dec A),
      cost _ _ (@Ret A eqd) 0;

  constant_cost_le :
    forall A B (f : A -> B) c1 c2,
      cost _ _ f c1 ->
      c1 <= c2 ->
      cost _ _ f c2;

  constant_cost_fst : 
    forall (A B : Type),
      cost _ _ (@fst A B) 0;

  constant_cost_snd : 
    forall (A B : Type),
      cost _ _ (@snd A B) 0;

  constant_cost_pair_1 : 
    forall (A B : Type),
      cost _ _ (@pair A B) 0;

  constant_cost_pair_2 : 
    forall (A B : Type) a,
      cost _ _ (@pair A B a) 0;

  constant_cost_pair : 
    forall (A B : Type),
      cost _ _ (fun p => @pair A B (fst p) (snd p)) 0;
  
  constant_cost_eqb_bool : 
    cost _ _ (fun p => @eqb bool _ (fst p) (snd p)) 1;

  constant_cost_bvxor : 
    forall eta, 
      cost _ _ (fun p => BVxor eta (fst p) (snd p)) eta;

  constant_cost_firstn : 
    forall k (A : Type),
      cost _ _ (@firstn A k) k;
  
  constant_cost_skipn : 
    forall k (A : Type),
      cost _ _ (@skipn A k) k;

  constant_cost_tl : 
    forall (A : Type),
      cost _ _ (@tl A) 1;
  
  constant_cost_hd : 
    forall (A : Type)(a : A),
      cost _ _ (hd a) 1;

  constant_cost_if_bool_f :
    forall (A B : Type)(f1 : A -> bool)(f2 f3 : A -> B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      cost _ _ f3 c3 ->
      cost _ _ (fun a => if (f1 a) then (f2 a) else (f3 a)) (c1 + c2 + c3)

}.Class constant_cost_relation(cost : CostModel) :={

  constant_cost_const : 
  forall (A B : Type)(b : B),
    cost _ _ (fun (_ : A) => b) 0;

  constant_cost_pair_args : 
  forall (A B C : Type)
    (f : A -> B -> C) c,
    cost _ _ (fun p => f (fst p) (snd p)) c ->
    exists c1 c2,
    cost _ _ f c1 /\ (forall a, cost _ _ (f a) c2) /\ c1 + c2 <= c;

  constant_cost_unpair_args : 
  forall (A B C : Type)
    (f : (A * B) -> C) c,
    cost _ _ f c ->
    cost _ _ (fun a b => f (a, b)) 0 /\
    (forall a, cost _ _ (fun b => f (a, b)) c);

  constant_cost_compose : 
  forall (A B C : Type)
    (f1 : A -> B)(f2 : A -> B -> C) c1 c2 c3,
    cost _ _ f1 c1 ->
    cost _ _ f2 c2 -> 
    (forall a, cost _ _ (f2 a) c3) -> 
    cost _ _ (fun a => f2 a (f1 a)) (c1 + c2 + c3);

  constant_cost_bind :
    forall (Z : Type)(A B : Set)(f1 : Z -> Comp A) (f2 : Z -> A -> Comp B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      (forall z, cost _ _ (f2 z) c3) -> 
      cost _ _ (fun a => Bind (f1 a) (f2 a)) (c1 + c2 + c3);

  constant_cost_ret :
    forall (A : Set)(eqd : eq_dec A),
      cost _ _ (@Ret A eqd) 0;

  constant_cost_le :
    forall A B (f : A -> B) c1 c2,
      cost _ _ f c1 ->
      c1 <= c2 ->
      cost _ _ f c2;

  constant_cost_fst : 
    forall (A B : Type),
      cost _ _ (@fst A B) 0;

  constant_cost_snd : 
    forall (A B : Type),
      cost _ _ (@snd A B) 0;

  constant_cost_pair_1 : 
    forall (A B : Type),
      cost _ _ (@pair A B) 0;

  constant_cost_pair_2 : 
    forall (A B : Type) a,
      cost _ _ (@pair A B a) 0;

  constant_cost_pair : 
    forall (A B : Type),
      cost _ _ (fun p => @pair A B (fst p) (snd p)) 0;
  
  constant_cost_eqb_bool : 
    cost _ _ (fun p => @eqb bool _ (fst p) (snd p)) 1;

  constant_cost_bvxor : 
    forall eta, 
      cost _ _ (fun p => BVxor eta (fst p) (snd p)) eta;

  constant_cost_firstn : 
    forall k (A : Type),
      cost _ _ (@firstn A k) k;
  
  constant_cost_skipn : 
    forall k (A : Type),
      cost _ _ (@skipn A k) k;

  constant_cost_tl : 
    forall (A : Type),
      cost _ _ (@tl A) 1;
  
  constant_cost_hd : 
    forall (A : Type)(a : A),
      cost _ _ (hd a) 1;

  constant_cost_if_bool_f :
    forall (A B : Type)(f1 : A -> bool)(f2 f3 : A -> B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      cost _ _ f3 c3 ->
      cost _ _ (fun a => if (f1 a) then (f2 a) else (f3 a)) (c1 + c2 + c3)

}.Class constant_cost_relation(cost : CostModel) :={

  constant_cost_const : 
  forall (A B : Type)(b : B),
    cost _ _ (fun (_ : A) => b) 0;

  constant_cost_pair_args : 
  forall (A B C : Type)
    (f : A -> B -> C) c,
    cost _ _ (fun p => f (fst p) (snd p)) c ->
    exists c1 c2,
    cost _ _ f c1 /\ (forall a, cost _ _ (f a) c2) /\ c1 + c2 <= c;

  constant_cost_unpair_args : 
  forall (A B C : Type)
    (f : (A * B) -> C) c,
    cost _ _ f c ->
    cost _ _ (fun a b => f (a, b)) 0 /\
    (forall a, cost _ _ (fun b => f (a, b)) c);

  constant_cost_compose : 
  forall (A B C : Type)
    (f1 : A -> B)(f2 : A -> B -> C) c1 c2 c3,
    cost _ _ f1 c1 ->
    cost _ _ f2 c2 -> 
    (forall a, cost _ _ (f2 a) c3) -> 
    cost _ _ (fun a => f2 a (f1 a)) (c1 + c2 + c3);

  constant_cost_bind :
    forall (Z : Type)(A B : Set)(f1 : Z -> Comp A) (f2 : Z -> A -> Comp B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      (forall z, cost _ _ (f2 z) c3) -> 
      cost _ _ (fun a => Bind (f1 a) (f2 a)) (c1 + c2 + c3);

  constant_cost_ret :
    forall (A : Set)(eqd : eq_dec A),
      cost _ _ (@Ret A eqd) 0;

  constant_cost_le :
    forall A B (f : A -> B) c1 c2,
      cost _ _ f c1 ->
      c1 <= c2 ->
      cost _ _ f c2;

  constant_cost_fst : 
    forall (A B : Type),
      cost _ _ (@fst A B) 0;

  constant_cost_snd : 
    forall (A B : Type),
      cost _ _ (@snd A B) 0;

  constant_cost_pair_1 : 
    forall (A B : Type),
      cost _ _ (@pair A B) 0;

  constant_cost_pair_2 : 
    forall (A B : Type) a,
      cost _ _ (@pair A B a) 0;

  constant_cost_pair : 
    forall (A B : Type),
      cost _ _ (fun p => @pair A B (fst p) (snd p)) 0;
  
  constant_cost_eqb_bool : 
    cost _ _ (fun p => @eqb bool _ (fst p) (snd p)) 1;

  constant_cost_bvxor : 
    forall eta, 
      cost _ _ (fun p => BVxor eta (fst p) (snd p)) eta;

  constant_cost_firstn : 
    forall k (A : Type),
      cost _ _ (@firstn A k) k;
  
  constant_cost_skipn : 
    forall k (A : Type),
      cost _ _ (@skipn A k) k;

  constant_cost_tl : 
    forall (A : Type),
      cost _ _ (@tl A) 1;
  
  constant_cost_hd : 
    forall (A : Type)(a : A),
      cost _ _ (hd a) 1;

  constant_cost_if_bool_f :
    forall (A B : Type)(f1 : A -> bool)(f2 f3 : A -> B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      cost _ _ f3 c3 ->
      cost _ _ (fun a => if (f1 a) then (f2 a) else (f3 a)) (c1 + c2 + c3)

}.Class constant_cost_relation(cost : CostModel) :={

  constant_cost_const : 
  forall (A B : Type)(b : B),
    cost _ _ (fun (_ : A) => b) 0;

  constant_cost_pair_args : 
  forall (A B C : Type)
    (f : A -> B -> C) c,
    cost _ _ (fun p => f (fst p) (snd p)) c ->
    exists c1 c2,
    cost _ _ f c1 /\ (forall a, cost _ _ (f a) c2) /\ c1 + c2 <= c;

  constant_cost_unpair_args : 
  forall (A B C : Type)
    (f : (A * B) -> C) c,
    cost _ _ f c ->
    cost _ _ (fun a b => f (a, b)) 0 /\
    (forall a, cost _ _ (fun b => f (a, b)) c);

  constant_cost_compose : 
  forall (A B C : Type)
    (f1 : A -> B)(f2 : A -> B -> C) c1 c2 c3,
    cost _ _ f1 c1 ->
    cost _ _ f2 c2 -> 
    (forall a, cost _ _ (f2 a) c3) -> 
    cost _ _ (fun a => f2 a (f1 a)) (c1 + c2 + c3);

  constant_cost_bind :
    forall (Z : Type)(A B : Set)(f1 : Z -> Comp A) (f2 : Z -> A -> Comp B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      (forall z, cost _ _ (f2 z) c3) -> 
      cost _ _ (fun a => Bind (f1 a) (f2 a)) (c1 + c2 + c3);

  constant_cost_ret :
    forall (A : Set)(eqd : eq_dec A),
      cost _ _ (@Ret A eqd) 0;

  constant_cost_le :
    forall A B (f : A -> B) c1 c2,
      cost _ _ f c1 ->
      c1 <= c2 ->
      cost _ _ f c2;

  constant_cost_fst : 
    forall (A B : Type),
      cost _ _ (@fst A B) 0;

  constant_cost_snd : 
    forall (A B : Type),
      cost _ _ (@snd A B) 0;

  constant_cost_pair_1 : 
    forall (A B : Type),
      cost _ _ (@pair A B) 0;

  constant_cost_pair_2 : 
    forall (A B : Type) a,
      cost _ _ (@pair A B a) 0;

  constant_cost_pair : 
    forall (A B : Type),
      cost _ _ (fun p => @pair A B (fst p) (snd p)) 0;
  
  constant_cost_eqb_bool : 
    cost _ _ (fun p => @eqb bool _ (fst p) (snd p)) 1;

  constant_cost_bvxor : 
    forall eta, 
      cost _ _ (fun p => BVxor eta (fst p) (snd p)) eta;

  constant_cost_firstn : 
    forall k (A : Type),
      cost _ _ (@firstn A k) k;
  
  constant_cost_skipn : 
    forall k (A : Type),
      cost _ _ (@skipn A k) k;

  constant_cost_tl : 
    forall (A : Type),
      cost _ _ (@tl A) 1;
  
  constant_cost_hd : 
    forall (A : Type)(a : A),
      cost _ _ (hd a) 1;

  constant_cost_if_bool_f :
    forall (A B : Type)(f1 : A -> bool)(f2 f3 : A -> B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      cost _ _ f3 c3 ->
      cost _ _ (fun a => if (f1 a) then (f2 a) else (f3 a)) (c1 + c2 + c3)

}.Class constant_cost_relation(cost : CostModel) :={

  constant_cost_const : 
  forall (A B : Type)(b : B),
    cost _ _ (fun (_ : A) => b) 0;

  constant_cost_pair_args : 
  forall (A B C : Type)
    (f : A -> B -> C) c,
    cost _ _ (fun p => f (fst p) (snd p)) c ->
    exists c1 c2,
    cost _ _ f c1 /\ (forall a, cost _ _ (f a) c2) /\ c1 + c2 <= c;

  constant_cost_unpair_args : 
  forall (A B C : Type)
    (f : (A * B) -> C) c,
    cost _ _ f c ->
    cost _ _ (fun a b => f (a, b)) 0 /\
    (forall a, cost _ _ (fun b => f (a, b)) c);

  constant_cost_compose : 
  forall (A B C : Type)
    (f1 : A -> B)(f2 : A -> B -> C) c1 c2 c3,
    cost _ _ f1 c1 ->
    cost _ _ f2 c2 -> 
    (forall a, cost _ _ (f2 a) c3) -> 
    cost _ _ (fun a => f2 a (f1 a)) (c1 + c2 + c3);

  constant_cost_bind :
    forall (Z : Type)(A B : Set)(f1 : Z -> Comp A) (f2 : Z -> A -> Comp B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      (forall z, cost _ _ (f2 z) c3) -> 
      cost _ _ (fun a => Bind (f1 a) (f2 a)) (c1 + c2 + c3);

  constant_cost_ret :
    forall (A : Set)(eqd : eq_dec A),
      cost _ _ (@Ret A eqd) 0;

  constant_cost_le :
    forall A B (f : A -> B) c1 c2,
      cost _ _ f c1 ->
      c1 <= c2 ->
      cost _ _ f c2;

  constant_cost_fst : 
    forall (A B : Type),
      cost _ _ (@fst A B) 0;

  constant_cost_snd : 
    forall (A B : Type),
      cost _ _ (@snd A B) 0;

  constant_cost_pair_1 : 
    forall (A B : Type),
      cost _ _ (@pair A B) 0;

  constant_cost_pair_2 : 
    forall (A B : Type) a,
      cost _ _ (@pair A B a) 0;

  constant_cost_pair : 
    forall (A B : Type),
      cost _ _ (fun p => @pair A B (fst p) (snd p)) 0;
  
  constant_cost_eqb_bool : 
    cost _ _ (fun p => @eqb bool _ (fst p) (snd p)) 1;

  constant_cost_bvxor : 
    forall eta, 
      cost _ _ (fun p => BVxor eta (fst p) (snd p)) eta;

  constant_cost_firstn : 
    forall k (A : Type),
      cost _ _ (@firstn A k) k;
  
  constant_cost_skipn : 
    forall k (A : Type),
      cost _ _ (@skipn A k) k;

  constant_cost_tl : 
    forall (A : Type),
      cost _ _ (@tl A) 1;
  
  constant_cost_hd : 
    forall (A : Type)(a : A),
      cost _ _ (hd a) 1;

  constant_cost_if_bool_f :
    forall (A B : Type)(f1 : A -> bool)(f2 f3 : A -> B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      cost _ _ f3 c3 ->
      cost _ _ (fun a => if (f1 a) then (f2 a) else (f3 a)) (c1 + c2 + c3)

}.Class constant_cost_relation(cost : CostModel) :={

  constant_cost_const : 
  forall (A B : Type)(b : B),
    cost _ _ (fun (_ : A) => b) 0;

  constant_cost_pair_args : 
  forall (A B C : Type)
    (f : A -> B -> C) c,
    cost _ _ (fun p => f (fst p) (snd p)) c ->
    exists c1 c2,
    cost _ _ f c1 /\ (forall a, cost _ _ (f a) c2) /\ c1 + c2 <= c;

  constant_cost_unpair_args : 
  forall (A B C : Type)
    (f : (A * B) -> C) c,
    cost _ _ f c ->
    cost _ _ (fun a b => f (a, b)) 0 /\
    (forall a, cost _ _ (fun b => f (a, b)) c);

  constant_cost_compose : 
  forall (A B C : Type)
    (f1 : A -> B)(f2 : A -> B -> C) c1 c2 c3,
    cost _ _ f1 c1 ->
    cost _ _ f2 c2 -> 
    (forall a, cost _ _ (f2 a) c3) -> 
    cost _ _ (fun a => f2 a (f1 a)) (c1 + c2 + c3);

  constant_cost_bind :
    forall (Z : Type)(A B : Set)(f1 : Z -> Comp A) (f2 : Z -> A -> Comp B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      (forall z, cost _ _ (f2 z) c3) -> 
      cost _ _ (fun a => Bind (f1 a) (f2 a)) (c1 + c2 + c3);

  constant_cost_ret :
    forall (A : Set)(eqd : eq_dec A),
      cost _ _ (@Ret A eqd) 0;

  constant_cost_le :
    forall A B (f : A -> B) c1 c2,
      cost _ _ f c1 ->
      c1 <= c2 ->
      cost _ _ f c2;

  constant_cost_fst : 
    forall (A B : Type),
      cost _ _ (@fst A B) 0;

  constant_cost_snd : 
    forall (A B : Type),
      cost _ _ (@snd A B) 0;

  constant_cost_pair_1 : 
    forall (A B : Type),
      cost _ _ (@pair A B) 0;

  constant_cost_pair_2 : 
    forall (A B : Type) a,
      cost _ _ (@pair A B a) 0;

  constant_cost_pair : 
    forall (A B : Type),
      cost _ _ (fun p => @pair A B (fst p) (snd p)) 0;
  
  constant_cost_eqb_bool : 
    cost _ _ (fun p => @eqb bool _ (fst p) (snd p)) 1;

  constant_cost_bvxor : 
    forall eta, 
      cost _ _ (fun p => BVxor eta (fst p) (snd p)) eta;

  constant_cost_firstn : 
    forall k (A : Type),
      cost _ _ (@firstn A k) k;
  
  constant_cost_skipn : 
    forall k (A : Type),
      cost _ _ (@skipn A k) k;

  constant_cost_tl : 
    forall (A : Type),
      cost _ _ (@tl A) 1;
  
  constant_cost_hd : 
    forall (A : Type)(a : A),
      cost _ _ (hd a) 1;

  constant_cost_if_bool_f :
    forall (A B : Type)(f1 : A -> bool)(f2 f3 : A -> B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      cost _ _ f3 c3 ->
      cost _ _ (fun a => if (f1 a) then (f2 a) else (f3 a)) (c1 + c2 + c3)

}.Class constant_cost_relation(cost : CostModel) :={

  constant_cost_const : 
  forall (A B : Type)(b : B),
    cost _ _ (fun (_ : A) => b) 0;

  constant_cost_pair_args : 
  forall (A B C : Type)
    (f : A -> B -> C) c,
    cost _ _ (fun p => f (fst p) (snd p)) c ->
    exists c1 c2,
    cost _ _ f c1 /\ (forall a, cost _ _ (f a) c2) /\ c1 + c2 <= c;

  constant_cost_unpair_args : 
  forall (A B C : Type)
    (f : (A * B) -> C) c,
    cost _ _ f c ->
    cost _ _ (fun a b => f (a, b)) 0 /\
    (forall a, cost _ _ (fun b => f (a, b)) c);

  constant_cost_compose : 
  forall (A B C : Type)
    (f1 : A -> B)(f2 : A -> B -> C) c1 c2 c3,
    cost _ _ f1 c1 ->
    cost _ _ f2 c2 -> 
    (forall a, cost _ _ (f2 a) c3) -> 
    cost _ _ (fun a => f2 a (f1 a)) (c1 + c2 + c3);

  constant_cost_bind :
    forall (Z : Type)(A B : Set)(f1 : Z -> Comp A) (f2 : Z -> A -> Comp B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      (forall z, cost _ _ (f2 z) c3) -> 
      cost _ _ (fun a => Bind (f1 a) (f2 a)) (c1 + c2 + c3);

  constant_cost_ret :
    forall (A : Set)(eqd : eq_dec A),
      cost _ _ (@Ret A eqd) 0;

  constant_cost_le :
    forall A B (f : A -> B) c1 c2,
      cost _ _ f c1 ->
      c1 <= c2 ->
      cost _ _ f c2;

  constant_cost_fst : 
    forall (A B : Type),
      cost _ _ (@fst A B) 0;

  constant_cost_snd : 
    forall (A B : Type),
      cost _ _ (@snd A B) 0;

  constant_cost_pair_1 : 
    forall (A B : Type),
      cost _ _ (@pair A B) 0;

  constant_cost_pair_2 : 
    forall (A B : Type) a,
      cost _ _ (@pair A B a) 0;

  constant_cost_pair : 
    forall (A B : Type),
      cost _ _ (fun p => @pair A B (fst p) (snd p)) 0;
  
  constant_cost_eqb_bool : 
    cost _ _ (fun p => @eqb bool _ (fst p) (snd p)) 1;

  constant_cost_bvxor : 
    forall eta, 
      cost _ _ (fun p => BVxor eta (fst p) (snd p)) eta;

  constant_cost_firstn : 
    forall k (A : Type),
      cost _ _ (@firstn A k) k;
  
  constant_cost_skipn : 
    forall k (A : Type),
      cost _ _ (@skipn A k) k;

  constant_cost_tl : 
    forall (A : Type),
      cost _ _ (@tl A) 1;
  
  constant_cost_hd : 
    forall (A : Type)(a : A),
      cost _ _ (hd a) 1;

  constant_cost_if_bool_f :
    forall (A B : Type)(f1 : A -> bool)(f2 f3 : A -> B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      cost _ _ f3 c3 ->
      cost _ _ (fun a => if (f1 a) then (f2 a) else (f3 a)) (c1 + c2 + c3)

}.Class constant_cost_relation(cost : CostModel) :={

  constant_cost_const : 
  forall (A B : Type)(b : B),
    cost _ _ (fun (_ : A) => b) 0;

  constant_cost_pair_args : 
  forall (A B C : Type)
    (f : A -> B -> C) c,
    cost _ _ (fun p => f (fst p) (snd p)) c ->
    exists c1 c2,
    cost _ _ f c1 /\ (forall a, cost _ _ (f a) c2) /\ c1 + c2 <= c;

  constant_cost_unpair_args : 
  forall (A B C : Type)
    (f : (A * B) -> C) c,
    cost _ _ f c ->
    cost _ _ (fun a b => f (a, b)) 0 /\
    (forall a, cost _ _ (fun b => f (a, b)) c);

  constant_cost_compose : 
  forall (A B C : Type)
    (f1 : A -> B)(f2 : A -> B -> C) c1 c2 c3,
    cost _ _ f1 c1 ->
    cost _ _ f2 c2 -> 
    (forall a, cost _ _ (f2 a) c3) -> 
    cost _ _ (fun a => f2 a (f1 a)) (c1 + c2 + c3);

  constant_cost_bind :
    forall (Z : Type)(A B : Set)(f1 : Z -> Comp A) (f2 : Z -> A -> Comp B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      (forall z, cost _ _ (f2 z) c3) -> 
      cost _ _ (fun a => Bind (f1 a) (f2 a)) (c1 + c2 + c3);

  constant_cost_ret :
    forall (A : Set)(eqd : eq_dec A),
      cost _ _ (@Ret A eqd) 0;

  constant_cost_le :
    forall A B (f : A -> B) c1 c2,
      cost _ _ f c1 ->
      c1 <= c2 ->
      cost _ _ f c2;

  constant_cost_fst : 
    forall (A B : Type),
      cost _ _ (@fst A B) 0;

  constant_cost_snd : 
    forall (A B : Type),
      cost _ _ (@snd A B) 0;

  constant_cost_pair_1 : 
    forall (A B : Type),
      cost _ _ (@pair A B) 0;

  constant_cost_pair_2 : 
    forall (A B : Type) a,
      cost _ _ (@pair A B a) 0;

  constant_cost_pair : 
    forall (A B : Type),
      cost _ _ (fun p => @pair A B (fst p) (snd p)) 0;
  
  constant_cost_eqb_bool : 
    cost _ _ (fun p => @eqb bool _ (fst p) (snd p)) 1;

  constant_cost_bvxor : 
    forall eta, 
      cost _ _ (fun p => BVxor eta (fst p) (snd p)) eta;

  constant_cost_firstn : 
    forall k (A : Type),
      cost _ _ (@firstn A k) k;
  
  constant_cost_skipn : 
    forall k (A : Type),
      cost _ _ (@skipn A k) k;

  constant_cost_tl : 
    forall (A : Type),
      cost _ _ (@tl A) 1;
  
  constant_cost_hd : 
    forall (A : Type)(a : A),
      cost _ _ (hd a) 1;

  constant_cost_if_bool_f :
    forall (A B : Type)(f1 : A -> bool)(f2 f3 : A -> B) c1 c2 c3,
      cost _ _ f1 c1 ->
      cost _ _ f2 c2 ->
      cost _ _ f3 c3 ->
      cost _ _ (fun a => if (f1 a) then (f2 a) else (f3 a)) (c1 + c2 + c3)

}.

Theorem constant_cost_compose_binary : forall (A B C D: Type) (f1 : A -> B)(f2 : A ->C)(f3 : B -> C -> D) c1 c2 c3 c4, cost f1 c1 -> cost f2 c2 -> cost f3 c3 -> (forall b, cost (f3 b) c4) -> cost (fun a => f3 (f1 a) (f2 a)) (c1 + c2 + c3 + c4).