Set Implicit Arguments.
Require Import List.
Require Import MyTactics.
Require Import Types.
Require Import TypeEquality.
Require Import MoreTypeEquality.
 ------------------------------------------------------------------------- 
 Tactics for proving type equality goals, while exploiting the equational
   theory of tensor. (Because tyeq is not intensional equality, we cannot
   use autorewrite.) 
 eqth_step assumes that the goal is the form tyeq (TyTensor _ _) _, and
   tries to solve it using a single law of the equational theory. If the
   right-hand side is a unification variable, it is instantiated. 
Ltac eqth_step :=
  
first [
    
eapply tyeq_tensor_arrow
  | 
eapply tyeq_tensor_pair
  | 
eapply tyeq_tensor_unit
  | 
eapply tyeq_tensor_q
  | 
eapply tyeq_tensor_bang
  | 
eapply tyeq_tensor_ref
  | 
eapply tyeq_tensor_at
  | 
eapply tyeq_tensor_regioncap
  | 
eapply tyeq_tensor_regioncappunched
  | 
eapply tensor_subst
  ]; 
wf.
 TEMPORARY instead of this costly disjunction, one could/should use the lemma tyred_tyeq directly 
 eqth assumes that the goal is the form tyeq (TyTensor _ _) _, and tries
   to solve it using at least one step, and as many steps as possible, in the
   equational theory. 
Ltac eqth :=
  
eapply tyeq_transitive; [ 
eqth_step | 
prove_tyeq | 
wf ]
 prove_tyeq attempts to prove the goal, if it is of the form tyeq _ _
   or wf _. It simplifies applications of tensor. 
with prove_tyeq :=
  
match goal with
 First, try exploiting the equational theory. 
  | |- 
tyeq (
TyTensor _ _) 
_ =>
      
eqth
  | |- 
tyeq _ (
TyTensor _ _) =>
      
eapply tyeq_symmetric; 
eqth
 Otherwise, try decomposing the goal; instantiate unification variables
     if required. If decomposition does not work, try reflexivity. 
  | |- 
tyeq _ _ =>
      
first [
        
eapply tyeq_var
      | 
eapply tyeq_arrow
      | 
eapply tyeq_pair
      | 
eapply tyeq_q
      | 
eapply tyeq_bang
      | 
eapply tyeq_ref
      | 
eapply tyeq_region
      | 
eapply tyeq_at
      | 
eapply tyeq_regioncap
      | 
eapply tyeq_regioncappunched
      | 
eapply tyeq_reflexive
      ]; 
prove_tyeq
 If this is a well-formedness goal, kill it. 
  | |- 
wf _ =>
      
wf
 If none of this works, give up. 
  | 
_ =>
      
idtac
  end.
 tyeq_under_tensor attempts to work under a tensor. If both sides of the
   goal exhibit a tensor, then tyeq_tensor is applied in order to work under
   the tensor.  If only the left-hand side of the goal exhibits a tensor, then
   transitivity is invoked, and tyeq_tensor is applied on the left-hand
   side, in order to again work under the tensor. 
Ltac tyeq_under_tensor :=
  
match goal with
  | |- 
tyeq (
TyTensor _ ?
u) (
TyTensor _ ?
u) =>
      
eapply tyeq_tensor; [ 
idtac | 
eapply tyeq_reflexive; 
wf ]
  | |- 
tyeq (
tensors _ ?
us) (
tensors _ ?
us) =>
      
eapply tyeq_tensors; [ 
wf | 
idtac ]
  | |- 
tyeq (
TyTensor _ _) 
_ =>
      
eapply tyeq_transitive; [ 
eapply tyeq_tensor; [ 
idtac | 
eapply tyeq_reflexive; 
wf ] | 
idtac | 
idtac ]
  | |- 
tyeq (
tensors _ _) 
_ =>
      
eapply tyeq_transitive; [ 
eapply tyeq_tensors; [ 
wf | 
idtac ] | 
idtac | 
idtac ]
  
end.