Documentation

Lean.Meta.Coe

Tags declarations to be unfolded during coercion elaboration.

This is mostly used to hide coercion implementation details and show the coerced result instead of an application of auxiliary definitions (e.g. CoeT.coe, Coe.coe). This attribute only works on reducible functions and instance projections.

def Lean.Meta.isCoeDecl (env : Environment) (declName : Name) :

Return true iff declName is one of the auxiliary definitions/projections used to implement coercions.

Equations
    Instances For

      Expands coercions occurring in e and return the result together with a list of applied Coe instances.

      Equations
        Instances For

          Coerces expr to expectedType using CoeT.

          Equations
            Instances For
              def Lean.Meta.coerceSimple? (expr expectedType : Expr) :

              Coerces expr to expectedType using CoeT.

              Equations
                Instances For

                  Coerces expr to a function type.

                  Equations
                    Instances For

                      Coerces expr to a type.

                      Equations
                        Instances For

                          Return some (m, α) if type can be reduced to an application of the form m α using [reducible] transparency.

                          Equations
                            Instances For

                              Return true if type is of the form m α where m is a Monad. Note that we reduce type using transparency [reducible].

                              Equations
                                Instances For
                                  def Lean.Meta.coerceMonadLift? (e expectedType : Expr) :

                                  Try coercions and monad lifts to make sure e has type expectedType.

                                  If expectedType is of the form n β, we try monad lifts and other extensions.

                                  Extensions for monads.

                                  1. Try to unify n and m. If it succeeds, then we use
                                  coeM {m : Type u → Type v} {α β : Type u} [∀ a, CoeT α a β] [Monad m] (x : m α) : m β
                                  

                                  n must be a Monad to use this one.

                                  1. If there is monad lift from m to n and we can unify α and β, we use
                                  liftM : ∀ {m : Type u_1 → Type u_2} {n : Type u_1 → Type u_3} [self : MonadLiftT m n] {α : Type u_1}, m α → n α
                                  

                                  Note that n may not be a Monad in this case. This happens quite a bit in code such as

                                  def g (x : Nat) : IO Nat := do
                                    IO.println x
                                    pure x
                                  
                                  def f {m} [MonadLiftT IO m] : m Nat :=
                                    g 10
                                  
                                  
                                  1. If there is a monad lift from m to n and a coercion from α to β, we use
                                  liftCoeM {m : Type u → Type v} {n : Type u → Type w} {α β : Type u} [MonadLiftT m n] [∀ a, CoeT α a β] [Monad n] (x : m α) : n β
                                  

                                  Note that approach 3 does not subsume 1 because it is only applicable if there is a coercion from α to β for all values in α. This is not the case for example for pure $ x > 0 when the expected type is IO Bool. The given type is IO Prop, and we only have a coercion from decidable propositions. Approach 1 works because it constructs the coercion CoeT (m Prop) (pure $ x > 0) (m Bool) using the instance pureCoeDepProp.

                                  Note that, approach 2 is more powerful than tryCoe. Recall that type class resolution never assigns metavariables created by other modules. Now, consider the following scenario

                                  def g (x : Nat) : IO Nat := ...
                                  deg h (x : Nat) : StateT Nat IO Nat := do
                                  v ← g x;
                                  IO.Println v;
                                  ...
                                  

                                  Let's assume there is no other occurrence of v in h. Thus, we have that the expected of g x is StateT Nat IO, and the given type is IO Nat. So, even if we add a coercion.

                                  instance {α m n} [MonadLiftT m n] {α} : Coe (m α) (n α) := ...
                                  

                                  It is not applicable because TC would have to assign ?α := Nat. On the other hand, TC can easily solve [MonadLiftT IO (StateT Nat IO)] since this goal does not contain any metavariables. And then, we convert g x into liftM $ g x.

                                  Equations
                                    Instances For

                                      Coerces expr to the type expectedType. Returns .some (coerced, appliedCoeDecls) on successful coercion, .none if the expression cannot by coerced to that type, or .undef if we need more metavariable assignments.

                                      appliedCoeDecls is a list of names representing the names of the Coe instances that were applied.

                                      Equations
                                        Instances For
                                          def Lean.Meta.coerce? (expr expectedType : Expr) :

                                          Coerces expr to the type expectedType. Returns .some coerced on successful coercion, .none if the expression cannot by coerced to that type, or .undef if we need more metavariable assignments.

                                          Equations
                                            Instances For