Another situation where an expected type is not generally available is the function position in a function application term.
Dependent function types are common; together with implicit parameters, they cause information to flow from the elaboration of one argument to the elaboration of the others.
Attempting to deduce the type required for the function from the expected type of the entire application term and individually-inferred types of arguments will often fail.
In these situations, Lean uses the CoeFun type class to coerce a non-function in an application position into a function.
Like CoeSort, CoeFun instances do not chain with other coercions while inserting a function coercion, but they can be used as CoeOut instances during ordinary coercion insertion.
The second parameter to CoeFun is an output parameter that determines the resulting function type.
This output parameter is function that computes the function type from the term that's being coerced, rather than the function type itself.
Unlike CoeDep, the term itself is not taken into account during instance synthesis; it can, however, be used to create dependently typed coercions where the function type is determined by the term.
CoeFunα(γ:α→Sortv) is a coercion to a function. γa should be a
(coercion-to-)function type, and this is triggered whenever an element
f:α appears in an application like fx, which would not make sense since
f does not have a function type.
CoeFun instances apply to CoeOut as well.
Sometimes, the type of the resulting function depends on the specific value that is being coerced.
A Writer represents a means of appending a representation of some value to a string:
A well-typed interpreter is an interpreter for a programming language that uses indexed families to rule out run-time type errors.
Functions written in the interpreted language can be interpreted as Lean functions, but their underlying source code can also be inspected.
The first step in the well-typed interpreter is to select the subset of Lean types that can be used.
These types are represented by an inductive type of codes Ty and a function that maps these codes to actual types.
Because the OfNat instance for Fin requires that the upper bound be non-zero, Tm.var can be inconvenient to use with numeric literals.
The helper Tm.v can be used to avoid the need for type annotations in these cases.