Generic bidirectional typing for dependent type theories

Bidirectional typing is a discipline in which the typing judgment is decomposed explicitly into inference and checking modes, allowing to control the flow of type information in typing rules and to specify algorithmically how they should be used. Bidirectional typing has been fruitfully studied and bidirectional systems have been developed for many type theories. However, the formal development of bidirectional typing has until now been kept confined to specific theories, with general guidelines remaining informal. In this work, we give a generic account of bidirectional typing for a general class of dependent type theories. This is done by first giving a general definition of type theories (or equivalently, a logical framework), for which we define declarative and bidirectional type systems. We then show, in a theory-independent fashion, that the two systems are equivalent. Finally, we establish the decidability of bidirectional typing for normalizing theories, yielding a generic type-checking algorithm that has been implemented in a prototype and used in practice with many theories.


INTRODUCTION
When defining the syntax of programming languages and type theories, many choices are available.The approach of seeing such systems as algebraic theories 1  [8,18,32,62] leads one to consider fully-annotated syntaxes in which every type argument is spelled out explicitly: an application is written as @ , ., a dependent pair as , , ., cons as :: , etc. On the one hand, this choice of syntax is very natural because all the premises of typing rules get recorded in the syntax, as illustrated by the typing rule for , , .: Γ ⊢ , , .: Σ : .On the other hand, the verbosity of such type annotations unfortunately destroys any hope of practical usability.Fully-annotated terms are not only much slower to type-check and reduce, but it is also not reasonable to ask users of type theories to write all such annotations.Because of this, the type theories used in practice omit the majority of these annotations, so one writes for application, , for a dependent pair, :: for cons, etc.This unannotated syntax is so common that many might not even realize that an omission is being made.
The omission of type arguments has nevertheless a cost: because knowing them is still important when typing terms, it becomes unclear how to do this algorithmically, even when the definitional equality of the theory is decidable.For instance, if we omit the annotations in , , ., then when building a typing derivation for this term one has to guess the values of and : Γ ⊢ ?type Γ, : ?⊢ ?type Γ ⊢ : ?Γ ⊢ : ?
Bidirectional typing.A solution to this problem is provided by bidirectional typing [21,24,25,48,56], a typing discipline in which the declarative typing judgment Γ ⊢ : is decomposed explicitly into inference Γ ⊢ ⇒ , where Γ and are inputs and is an output, and checking Γ ⊢ ⇐ , where Γ, and are all inputs.The important point is that, by using these new judgments to control the flow of type information in typing rules, one can specify algorithmically how these rules should be used.For instance, the following rule clarifies how one should type , : the types and are not to be guessed, but instead recovered from the type , which should be given as input.
In general, whenever a term starts by a constructor (that is, an introduction form), bidirectional typing allows the recovery of annotations by asking its type to be given as input.Dually to how constructors can be type-checked, bidirectional typing supports type-inference of destructors (that is, of elimination forms) by recovering the missing arguments from the type of its first argument, which gets inferred.This can be illustrated with the bidirectional typing rule for application: We therefore see that bidirectional typing is the natural companion for an unannotated syntax, as it allows to algorithmically explain how the missing information can be retrieved.
Bidirectional typing has been fruitfully studied and bidirectional systems have been developed for many type theories [2,3,21,34,45,52].However, the formal development of bidirectional typing has until now remained confined to specific theories, with general guidelines remaining informal.One can then naturally wonder if it would be possible to define a framework in which bidirectional typing could be studied generically, putting its general theory in solid ground.This is exactly the goal of this paper.
Our contribution.We contribute a generic account of bidirectional typing for a general class of dependent type theories.
In order to study bidirectional typing generically, our first contribution is to give a general definition of type theories (or equivalently, a logical framework).Our proposal is much inspired by previous frameworks such as Uemura's SOGATs [63] and Haselwarter and Bauer's FTTs [39], yet differs from them in significant ways, in particular by allowing for the usual unannotated syntaxes most often used in practice -after all, bidirectional typing is only interesting for explaining why annotations can be omitted -, and being more geared towards implementation by only supporting definitional equalities defined by rewrite rules.
Our notion of theory then allows for two kinds of entries: rewrite rules and schematic typing rules, for specifying the theory's typing relation.One important feature of our proposal is the separation of (term-level) schematic rules as either constructor or destructor rules, motivated by the differences of their roles with regards to bidirectionality.The schematic rules can then be instantiated into actual typing rules, yielding the main type system associated with the theory, which we refer to as declarative in order to distinguish it from the bidirectional system.We then establish that, for each of the theories, its associated declarative system satisfies desirable properties, like weakening and substitution.These properties are not only good sanity checks, but also essential for when establishing the correctness of the bidirectional type system subsequently.
To formulate our bidirectional system we address the well-known problem that some unannotated terms cannot be algorithmically typed -a limitation that is not at all specific to bidirectional typing [23].This is typically the case for redices like ( . ) : while the bidirectional rule for application requires the type of its first argument to be inferred, the rule for abstraction requires its type to be given an input.To rule out this issue, we define our bidirectional system over a syntax of inferable and checkable terms, in which an ascription :: must be inserted when a destructor meets a constructor -similarly to bidirectional typing à la McBride [48].
We then prove our main results, showing the correctness of the bidirectional type system with respect to the declarative one.We first establish soundness, ensuring that any term typed by the bidirectional system is also typable by the declarative one when forgetting about ascriptions.Dually, we show annotability [24], ensuring that any (declaratively) typed term can be sufficiently annotated with ascriptions to get a term typable by the bidirectional system.Finally, we also show that the bidirectional system is decidable for strongly-normalizing theories, allowing it to be used for typing terms algorithmically.We emphasize that we do not show theses results for a specific type theory but instead for a whole general class of theories.
The implementation.The framework we develop is not only of theoretical interest, but also has important practical applications.The decidability result for our bidirectional system allowed us to implement it in the theory-independent type-checker BiTTs, publicly available at https://doi.org/10.5281/zenodo.10996395This has allowed our system to be used in practice with multiple theories, from variants of Martin-Löf Type Theory, to Higher-Order Logic and Observational Type Theory.
Moreover, because our framework allows for defining theories with less annotations in the syntax, we expect it to allow for better performances when compared with other theory-independent type-checkers such as Dedukti, in which the lack of support for omitting annotations can have an important impact on type-checking times [28,Section 9].
Finally, our implementation can also be used to prototype with new type theories without having to implement a new bidirectional algorithm from scratch, an important commodity given the large number of new theories that are proposed each year.
Plan of the paper.We start in Section 2 by formulating our general definition of type theories, before moving to Section 3 in which we specify the declarative system of the theories and show its expected properties.Section 4 is then dedicated to the definition of the bidirectional type system and its proofs of correctness with respect to the declarative system and of decidability.We then give in Section 5 more examples of theories covered by our framework, and discuss its implementation in Section 6.We finish by discussing related work in Section 7 before concluding with Section 8.

Related version.
A preliminary version of our work had first appeared in the proceedings of the 33rd European Symposium on Programming [29].This version contains multiple improvements, among which are the following: • We have addressed the main deficiency of our preliminary work, which was its lack of support for indexed types, such as vectors and, most importantly, the equality type: our notion of theory has been updated in order to support such types.• We have extended the bidirectional syntax by adding support for ascriptions, allowing to turn a checkable term into an inferable one :: .Accordingly, our notion of completeness has been updated to annotability, as discussed in the introduction.Our previous completeness result, here called ascription-free completeness, is now shown as a simple corollary of annotability.• Our treatment of matching modulo rewriting has been simplified, in particular by removing its reliance on the maximal-outermost strategy.This brings the theory closer to our implementation, where we use a reduction strategy based on call-by-value.
• The section on examples of theories covered by our framework has been considerably extended, better illustrating the generality of our approach.• Finally, due the space constraints, the proofs of our results could only be sketched in our preliminary version, whereas this extended version provides detailed proofs.

A GENERAL DEFINITION OF BIDIRECTIONAL TYPE THEORIES
In this section, we give a general definition of type theories (or equivalently, a logical framework) for which we will give declarative and bidirectional type systems in later sections.We start the section by defining the raw syntax of our theories.Then, after defining patterns and substitution, we give one of the central definitions of our work: the one of theory.We finish the section by describing the rewrite judgment used to specify the definitional equality of our type theories.
2.1 Raw Syntax 2.1.1Intrinsically-scoped syntax.When defining the syntax of type theory, one most usually defines a set Tm containing all terms.However, it is sometimes useful to distinguish terms ∈ Tm according to the variables that can appear in -for instance, when defining the application of a substitution, it is useful to know that it is defined for all variables in .Therefore, we elect an intrinsically-scoped presentation of syntax, in which we define instead a family of terms, indexed by scopes specifying which variables can appear.
2.1.2Scopes and signatures.The basic ingredients of our raw expressions are actually not only variables , , . . ., but also metavariables x, y, . . .and operations , . . ., which are specified respectively by (variable) scopes, metavariable scopes and signatures.

Scope ∋
A scope is simply a list of variables, whereas a metavariable scope is a list of metavariables accompanied by a variable scope , explaining the arguments each metavariable expects.For instance, x{ , } ∈ specifies a metavariable x taking two arguments, each one named by the variables or .We have an obvious operation of concatenation .and ., for variable scopes and metavariable scopes respectively.A signature Σ is then a list of operations accompanied by a metavariable scope explaining its arguments: for instance, (x{•}, y{ }) ∈ Σ specifies an operation taking two arguments and binding one variable in its second argument.We allow ourselves to abbreviate x{•} as x and (•) as when convenient.Finally, we suppose that operations are partitioned between constructors , whose names we write in blue, and destructors , whose names we write in orange.
Example 2.1.The following signature Σ Π defines the raw syntax of a minimalistic Martin-Löf Type Theory (MLTT) with only dependent functions.Ty, Tm(A), Π(A, B{ }), (t{ }), @(t, u) The operations are the ones we would expect, except for Ty and Tm whose role will become clear later.
Remark 2.2.When working with de Bruijn indices, a scope becomes just a natural number and a metavariable scope becomes just a list of natural numbers.In this setting, our definition of signatures corresponds exactly to the well-known binding-signatures [7,30], where 2.1.3Terms and substitutions.Given a fixed signature Σ, we define terms, (variable) substitutions and metavariable substitutions by the following grammars.Note that, as explained before, we do not define a set of terms but instead a family Tm in which the indices and explain which metavariables and variables are in scope.

Tm
∋ , , , A term is either a variable , a metavariable x applied to a substitution ì , or an operation applied to a metavariable substitution t.A (variable) substitution ì ∈ Sub is then simply a list of terms, in which each term corresponds to one of the variables in .Similarly, a metavariable substitution t ∈ MSub is also a list of terms, with the difference that each position x{ } ∈ extends the current scope with the variables in .We write this variable binding as ì ., which can be seen in action in the cases of and Π in Example 2.3.Finally, we allow ourselves to abbreviate x{ } as x and ( ) as when convenient.
Example 2.3.The terms defined by the signature Σ Π are given by the following grammar, where we omit the scope requirements for variables and metavariables.
, , , : Given a metavariable substitution t ∈ MSub and x{ } ∈ , we write t x ∈ Tm .for the term in t at the position pointed by x.Similarly, given a substitution ì ∈ Sub and ∈ , we write ∈ Tm for the term in ì at the position pointed by .For each and we have the identity substitutions id ∈ Sub (•) and id ∈ MSub (•) , defined by id (•) := and id , := id , and id ,x{ } := id , ì .x{id}.Note that, while the identity variable substitution id is just the list of variables from , the identity metavariable substitution id needs to "eta-expand" each metavariable x{ } ∈ to ì .x{id} in order for the result to be a valid metavariable substitution.Finally, we allow ourselves to omit the index of id or id when it can be inferred from the context.Remark 2.5.We work with a nameful syntax, allowing us to implicitly weaken expressions: if ∈ Expr and is a subsequence of ′ and is a subsequence of ′ then we also have ∈ Expr ′ ′ .Nevertheless, we expect that our proofs can be formally carried out using de Bruijn indices, by properly inserting weakenings whenever needed, and showing the associated lemmata.
2.1.5Substitution application.We define in Figure 1 the application of a (variable or metavariable) substitution to an expression.Given a variable substitution ì ∈ Sub x we get ì [v] ∈ Sub 1 .x .We moreover have v x ∈ Tm 1 .x , so by substituting the variables in x by ì [v] and the ones in by themselves we get v x [id, ì [v]] ∈ Tm 1 .as the final result.
Remark 2.7.Compared to frameworks derived from contextual modal type theory [51], our metavariable substitutions are not required to be closed and can introduce new variables in the scope of the resulting term.For instance, in the previous example, while the term @( ( .t{}), u) lives in an empty variable scope, the application of the metavariable substitution yields @( ( .), ), which lives in the scope .Therefore, a metavariable t{ 1 , . . ., } should not be seen as a placeholder for a term containing only 1 , . . ., , but instead for a term in any scope extended by 1 , . . ., .

P
. All results are shown by induction on , on the following order: first 2.1.6Pa erns.We finish this subsection by isolating the pattern fragment of the syntax, which will be used in the next subsection to define the theories.Given a signature Σ, term patterns and metavariables substitution patterns are defined by the following grammars.
Compared with the regular syntax, the pattern condition imposes that each metavariable x{ } ∈ must occur precisely once, and moreover applied to all variables occurring in the scope of its occurrence -in particular, imposing it to be equal to .These restrictions ensure that, differently from regular terms, patterns support decidable and unitary matching [50].However, as we will see in Section 4.1, we will not only need syntactic matching but also matching modulo rewriting, leading us also to additionally impose that only constructors may appear in patterns.

Note that we have inclusions Tm P
⊂ Tm and MSub P ⊂ MSub , which we use to implicitly coerce patterns into regular expressions when needed.

Theories
We now come to a central definition in our work, that of a theory T ∈ Thy.We define inductively how a theory is built, simultaneously with its underlying signature |T| ∈ Sig -technically, our definition is by small induction-recursion [27].Assuming that a theory T is given we show how to extend it with two types of entries: schematic typing rules and rewrite rules.We start with the first, which come in three kinds: sort, constructor and destructor rules.

Sort rules.
In our framework, a sort is a term that can appear in the second position of the typing judgment : . 2 Like in algebraic presentations of type theory [18,62,63], the sorts of a theory correspond to its judgment forms.For instance, vanilla Martin-Löf Type Theory features two judgment forms: type, for asserting that is a type, and : for asserting that is a term of type .In our framework, these are materialized by the following sort rules.

Ty sort
A : Ty Tm(A) sort Formally, a sort rule is actually of the form and the previously shown rules are just an informal notation for Ty(•) sort and Tm(A : Ty) sort.More precisely, our notation represents metavariables x{Γ} : ∈ Ξ as premises Γ ⊢ x : , or just x : when Γ is empty.In the following, we will make use of such informal representations in order to enhance readability of schematic rules.

Constructor rules.
As discussed in the introduction, the way in which missing arguments can be recovered in bidirectional typing is deeply linked with whether a symbol is a constructor or a destructor: whereas constructors support type-checking, destructors support type-inference.In order to capture this distinction, we classify our term-level schematic rules as either constructor or destructor rules, and we start by describing constructor rules.
In order to specify the distinction between the arguments that are missing or not from the syntax, we split them in two metavariable contexts: Ξ containing the omitted arguments (sometimes also referred to as erased), and Ξ containing the constructor arguments present in the syntax.Then, to ensure that the arguments in Ξ can be recovered from the sort given as input, our first idea is to ask the sort of the rule to be a pattern over the metavariables of Ξ , leading to rules of the form Note that, whereas Ξ is closed, Ξ is allowed to depend on the underlying scope of Ξ , so the sorts and contexts of the non-omitted arguments can depend on the missing information.Two examples of rules fitting this definition are the ones for Π and -note however that the one for Π is slightly degenerate, given that we have Ξ = • and thus no erased premises.Once again, these are just notations for the formal rules Π(• ; A : Ty, B{ : Tm(A)} : Ty) : Ty and (A : Ty, B{ : Tm(A)} : Ty ; t{ : Tm(A)} : Tm(B{ })) : Tm(Π(A, .B{ })).
In the rule for , Ξ stores the parameters of the dependent function type.This is actually not specific to this one example, but in general all non-indexed type constructors fit ( * ) when taking Ξ to be its parameters.The situation is however trickier when trying to handle indexed inductive types.Consider for instance the constructors refl for equality and cons for vectors.
A : Ty a : Tm(A) refl : Tm(Eq(A, a, a)) A : Ty n : Tm(Nat) t : Tm(A) l : Tm(Vec(A, n)) cons(n, t, l) : Tm(Vec(A, S(n))) In the case of refl, the metavariable a occurs non-linearly in its sort Tm(Eq(A, a, a)), which is therefore not a pattern in our sense.In the case of cons its sort actually is a pattern, however in order for the rule to fit ( * ) we would have to omit the size of the vector n.This in principe can appear to be a good thing, after all the goal of bidirectional typing is precisely to remove annotations that are not needed.However when writing the reduction rules associated with the eliminator for vectors we realize that n actually is needed.Indeed, the argument n is computationally-relevant, meaning that the result of a computation might depend on it, so it cannot be erased.
In order to account for such rules we propose to split the metavariables occurring in the sort of the rule between parameters Ξ and indices Ξ .Whereas the parameters correspond to the erased arguments of the rule, indices correspond to terms depending on Ξ and Ξ .More precisely, the metavariables Ξ are instantiated by an index metavariable substitution v living in the underlying scopes of Ξ and Ξ .This now yields the definitive form for our constructor rules: The previously shown rules for Π and still fit this scheme by taking Ξ = • and v = , however now the rules for refl and cons can also be defined: Here, we update our informal notation by writing the premise Γ ⊢ x ↦ → : for when the index substitution v instantiates the metavariable x{Γ} : ∈ Ξ with the term .These rules can thus be "parsed" into the formal notation as refl(A : Ty, a : Tm(A) ; • ; a/b : Tm(A)) : Tm(Eq(A, a, b)) and cons(A : Ty ; n : Tm(Nat), t : Tm(A), l : Tm(Vec(A, n)) ; S(n)/m : Tm(Nat)) : Tm(Vec(A, m)).
As we will see in Section 4, from the sort given as input we will now not only recover the parameters but also the expected values for the indices.Once we have type-checked the nonerased arguments, we will then have to check that, by replacing the parameters and non-erased arguments in v , we get something convertible to what we found before.For instance, in the case of the the rule for cons, we will need to check that the value of m is convertible to successor of the value of n.
Remark 2.12.Whenever a constructor has no erased arguments (like is the case for Π), we do not actually need its sort to be given as input, and if we wanted we could also bidirectionally type it in mode infer.Nevertheless, we will prefer to value uniformity by imposing that constructors should always be bidirectionally typed in mode check.

Destructor rules.
Whereas constructors support type-checking, destructors support typeinference.Therefore, instead of recovering the omitted arguments from the sort of the rule, they are retrieved by inferring the sort of a specific argument we call the principal argument.The arguments of a destructor rule are thus separated between erased arguments Ξ , the principal argument x : and the other non-omitted destructor arguments Ξ , where the sort of the principal argument should be a pattern over the metavariables of Ξ .We therefore have rules of the following form: The prime example of a destructor rule is the one for functional application: Fig. 2. Definition of theories which is just an informal notation for @(A : Ty, B{ : Tm(A)} : Ty ; t : Tm(Π(A, .B{ })) ; u : Tm(A)) : Tm(B{u}) Note that, in destructor rules, the principal argument is always the first non-erased argument.Because all the other non-erased arguments are typed in check mode, it is important that the erased arguments are known when typing them, given that their sorts or contexts might depend on the erased arguments.For instance, if we reorder the rule for application by placing u : Tm(A) before t : Tm(Π(A, .B{ })), then how could we type-check u against Tm(A) if A is still not known?A similar reasoning justifies why the context corresponding to the principal argument is always empty.Indeed, if we had principal arguments of the form x{Γ} : instead of x : , we would have to extend the current context by Γ before inferring x.However, Γ may make reference to the erased arguments which are still not known at this point.

Rewrite rules.
Finally, the last type of rules are rewrite rules, which specify the definitional equality (also known as conversion) of the theory.As suggested by our constructor/destructor separation of symbols, the left-hand sides of rewrite rules are to be headed by destructors.The right-hand side of the rule is then a term containing only the metavariables introduced by the left-hand side.The rewrite rules are hence of the form, where is such that ( ) ∈ |T|.
We shall also ask for a supplementary condition: in order to extend a theory T with a rule (t) ↦ −→ , there can be no rule for some v and v ′ .As discussed in the next subsection, this will ensure that the rewrite system of a theory is confluent by construction.
The prototypical example of a rewrite rule is the computation rule for functions: the -rule from the -calculus.
In the following we allow ourselves to omit the rule metavariable scope as it can be easily reconstructed by inspecting the rewrite rule's left hand side.

Underlying signature.
As explained in the beginning of the section, theories T ∈ Thy are specified mutually with their underlying signatures |T| ∈ Sig.We now give the definition of underlying signature, by the following clauses.As we can see, in both constructor and destructor rules the metavariable contexts of erased premises are indeed omitted from the syntax.Moreover, rewrite rules are simply ignored when computing the underlying signature.
This concludes the definition of our theories, which for ease of reference we recapitulate in Figure 2.

Rewriting
The rewrite rules of a theory T are used to define the rewriting relation −→ ′ in Figure 3.This definition is done simultaneously with the proof that reduction preserves underlying scopes: we have |Γ| = |Γ ′ | whenever Γ −→ Γ ′ , by an easy induction on Γ.The relations −→ * and ≡ are then defined as usual, respectively as the reflexive-transitive and reflexive-symmetric-transitive closures of −→.The relation ≡ is called the definitional equality (or conversion) of the theory.One of the key properties of rewriting is its stability under substitution: , by induction on , and then that −→ ′ implies [ì ] −→ ′ [ì ], by induction on −→ ′ .By iterating these two statements, we then conclude that −→ * ′ and ì , by induction on , and then that −→ ′ implies [v] −→ ′ [v], by induction on −→ ′ .By iterating these two statements, we then conclude that −→ * ′ and v This implies in particular that conversion is stable under substitution.

Confluence.
Recall that when defining theories we asked that no two different left-hand sides should unify.Because this is the only way two rule can overlap, this means that there are no critical pairs [15].Therefore, because rules are also all left-linear, it follows that the rewrite system of any theory is orthogonal, hence confluent by [47,Theorem 6.11].
One of the main consequences of confluence is that patterns are injective modulo conversion:

P
. We need to show simultaneously a similar result for metavariable substitution patterns: The proof is done by induction on the pattern, using confluence for the case

DECLARATIVE TYPE SYSTEM
In the previous section we have seen that theories are specified by rewrite rules and schematic typing rules.In this section, we shall see how such schematic rules can be instantiated into concrete typing rules, defining the declarative type system of the corresponding theory.This system is then used to define the valid theories, a refinement of our notion of theory in which typing information is also taken into account.We then conclude the section by showing that the declarative system satisfies desirable properties, such as weakening and substitution.

Declarative typing rules
Given a fixed theory T, the declarative type system is defined by the rules in Figure 4.The system is split in 6 judgments: .For instance, in order to use D to type (t) a metavariable substitution t not stored in the syntax must be "guessed", and then we must show that t , t is typed by Ξ .(x: ).Ξ .The rules for typing a metavariable substitution can then be applied, which has the effect of unfolding the judgment t , t : Ξ .(x: ).Ξ into regular term typing judgments.At the end of this unfolding process, the resulting derivation has basically the same shape as the schematic typing rule for , and it can be understood as its instantiation.Let us look at a concrete example of this.Example 3.1.Suppose we want to show that @( , ) is well-typed in the theory T Π .Because @ is a destructor symbol with schematic rule @(A : Ty, B{ : Tm(A)} : Ty ; t : Tm(Π(A, .B{ })) ; u : Tm(A)) : Tm(B{u}) by guessing some and we can start the derivation with rule D , giving Θ; Γ ⊢ , ., , : (A : Ty, B{ : Tm(A)} : Ty, t : Tm(Π(A, .B{ })), u : Tm(A)) If we note that Tm(B{u}) [ , ., , ] = Tm( [id Γ , ]), and we continue by applying the rules defining the judgment Θ; Γ ⊢ t : Ξ, we get Θ; Γ ⊢ Θ; Γ ⊢ : Ty Θ; Γ, : Tm( ) ⊢ : Ty Θ; Γ ⊢ : Tm(Π( , .)) Θ; Γ ⊢ : Tm( ) Θ; Γ ⊢ @( , ) : Tm( [id Γ , ]) which can be understood as the instantiation of the schematic rule for @.Note that sometimes the first three premises of this rule are omitted, but this is only justified because they are admissible from the other ones, a result we could also show here by applying results from Section 3.3.

Remark 3.2. In the rule for C
it might seem odd that we also ask the sort to be well-typed, whereas this hypothesis is not needed in rules D , M and V .The reason is that in the proof of Theorem 4.13 we will need to apply the induction hypothesis to the sort of the term (t), and thus we need a derivation of sort smaller than the one of (t) : we start with.Nevertheless, we will show in Section 3.3 that this extra hypothesis is admissible, allowing us to use the economic version of the rule when building derivations.A similar technique is also employed by Harper et al [38] and Abel et al [6].Notation 3.3.We finish this subsection by establishing some notations.
(1) We write Θ; Γ ⊢ J for any of the following:

Valid theories
Our definition of theories given in Section 2.2 specifies the desired syntax but imposes not typing constraints whatsoever, allowing for non-sensible and ill-behaved theories.But now that we have introduced typing rules, we can impose such constraints a posteriori by defining the valid theories.
Our first step to do this is to define the well-typed theories with the judgment T ⊢ specified by Figure 5.The definition of T ⊢ ensures that each time we extend a theory T with a schematic typing, T can justify that the new rule is well-typed.For sort rules (Ξ) sort this amounts to ensuring that the metavariable context Ξ is well-typed, whereas for destructor rules (Ξ ; x : ; Ξ ) : this means ensuring that is a well-typed sort in metavariable context Ξ .(x: ).Ξ -implying in particular that the metavariable context is also well-typed.For typing a constructor (Ξ ; Ξ ; v /Ξ ) : we do not only ask to be a well-typed sort in Ξ .Ξ , but also v to be typed by Ξ .However, the judgment Ξ .Ξ ⊢ v : Ξ would not be well-formed: in the definition of Θ; Γ ⊢ t : Ξ in Figure 4 we ask Ξ ∈ MCtx, meaning that metavariable substitutions can only be typed by closed metavariable contexts.To eliminate the dangling metavariables of Ξ , we therefore prefix it with Ξ and instead ask Ξ .Ξ ⊢ id, v : Ξ .Ξ to be derivable.
↦ −→ ) ⊢ Fig. 5. Well-typed theories Remark 3.4.Note that the definition of T ⊢ asks schematic typing rules to be typed incrementally, which excludes theories that rely on circularities -for instance, when a rule depends on itself to be well-typed.Nevertheless, by a form of weakening for theories we can still deduce that all schematic typing rules of T can also be typed in T itself (for instance, if (Ξ) sort ∈ T and T ⊢ then T ⊲ Ξ ⊢), a fact that we will often use without announcement in the proofs to come.
The definition of well-typed theory ensures that the schematic rules are well-behaved, however it imposes no restriction whatsoever on rewrite rules.To remedy this, let us say that a rewrite rule : for all Γ ∈ Ctx and ∈ Tm (•) |Γ| and v ∈ MSub (•) |Γ| .As we will see in the end of Section 3.3, this local form of subject reduction implies (global) subject reduction, allowing one to establish the latter more easily.We then say that a theory is valid if it is well-typed and all its rewrite rules are type-preserving.
Example 3.5.It is tedious but uncomplicated to see that the theory T Π is valid.Checking its well-typedness is straightfoward, the most interesting part is verifying that the -rule is typepreserving.In order to do this, we start with a generic derivation of Γ ⊢ @( ( .t{}), u) [ ., ] : , where Γ, , and ., are any, and we must show Γ ⊢ t{u}[ ., ] : .Note that we have @( ( .t{}), u) [ ., ] = @( ( .), ) and t{u}[ ., ] = [id, ], so we start by applying inversion of typing to Γ ⊢ @( ( .for some ′ , ′ with Tm(Π( , .)) ≡ Tm(Π( ′ , .′ )), which by Proposition 2.17 gives ≡ ′ and ≡ ′ .Now we can conclude by applying some of the methatheorems we will see in the next subsection, that crucially do not rely on type-preservation (which would otherwise incur a circularity in our reasoning) but only on well-typedness of the theory, which we already have at this point.More precisely, from the above derivations we can show Γ, : Tm( ) ⊢ and Γ, : Tm( ) ⊢ Tm( ) sort, so starting from Γ, : Tm( ′ ) ⊢ : Tm( ′ ) we can applying Proposition 3.9 and conversion to obtain Γ, : Tm( ) ⊢ : Tm( ).We can also show Γ ⊢ id, : (Γ, : Tm( )), so by Proposition 3.8 we then get Γ ⊢ [id, ] : Tm( [id, ]).Finally, by applying Proposition 3.10 to Γ ⊢ @( ( .), ) : we get Γ ⊢ sort, so by applying conversion with Tm( [id, ]) ≡ we conclude Γ ⊢ [id, ] : .Remark 3.6.Verifying that a theory is valid is often a tedious task, however we do not expect users of our framework to do such calculations by hand all the time.Indeed, our tool implements an automatic check that try to verify this condition automatically.The implemented criterion is incomplete, but works well in most common cases.

Metatheory
We now show some basic metaproperties satisfied by the declarative type system.Most of these properties hold even when the theory is not well-typed or valid, so such assumptions will be stated explicitly when needed.

P 3.7 (W ).
Let us write Γ ⊑ Δ if Γ is a subsequence of Δ, and Θ ⊑ Ξ if Θ is a subsequence of Ξ.The following rules are admissible.
In order for the induction to go through, we strengthen the first statement: instead we show that Θ; Γ.Γ ′ ⊢ J and Θ; Δ ⊢ and Γ ⊑ Δ imply Θ; Δ.Γ ′ ⊢ J .The proof is then by induction on Θ; Γ.Γ ′ ⊢ J for the first statement, and on Θ; Γ ⊢ J for the second.
Our theories also satisfy a substitution property, meaning that if Θ; Γ ⊢ J is derivable, then by applying any substitution typed by Γ or metavariable substitution typed by Θ the resulting judgment is still derivable.In order to state this property precisely, we first need to explain what it means to apply a substitution to a judgment J .This is specified by the following table.Note that in the case would not in general yield a wellformed judgment, given that v might introduce dangling variables in Δ [v].Therefore, we need to prefix Δ[v] with the context Γ of the substitution, and fill the positions with the identity id -the same trick we used in Section 3.2.This is also the reason why the application of a metavariable substitution is annotated with Γ. ).The following rules are admissible.
For the proof to go through, we strengthen the first statement in the following way: Then both statements can be shown by induction, on Θ; Δ.Γ ′ ⊢ J for the first statement, and Θ; Δ ⊢ J for the second.Most cases follow directly from the induction hypothesis, the basic properties of substitution (Propositions 2.8 to 2.10) and, for the rule C , from the stability of conversion under substitution (Corollary 2.15).We show the key cases, and illustrate the other ones by some representative cases.
• Case V of the first statement.
We have either : ∈ Γ ′ or : ∈ Δ.In the first case, we apply the i.
and so we also have , so by the substitution property for variable substitutions we get The declarative system of Figure 4 features a conversion rule allowing us to deduce : from : when ≡ .This rule can actually be strengthen to contexts in the following manner: P 3.9 (C ).The following rules are admissible.
We first show the first statement by induction on Δ, using Proposition 3.8.Then, for the proof of the second statement we instantiate the first with Θ; Δ ⊢ id : Δ to get Θ; Δ ⊢ id : Γ and then conclude by applying Proposition 3.8 and using the fact that J [id] = J .Using Proposition 3.10, the premise for typing the sort in rule C can now be dropped, as anticipated in Remark 3.2.In the following we allow ourselves to use this economic version of the rule C without announcement.

P 3.11 ("E " C
).The following rule is admissible when T is well-typed.Finally, we now show that asking rewrite rules to be type-preserving is sufficient to ensure subject reduction. 3

P
3.12 (S ).Suppose that the underlying theory is valid.Remark 3.13.We have shown subject reduction only for terms without metavariables.It is nevertheless possible to extend Proposition 3.12 to terms with metavariable by strengthening the typepreservation condition to Θ; Γ ⊢ [v] : implies Θ; Γ ⊢ [v] : for all Θ, Γ, v, .However, this generalization would be of no use for the proofs to come.

BIDIRECTIONAL TYPE SYSTEM
Having seen the definition of the declarative system, we move now to the bidirectional type system.We start the section by discussing matching modulo rewriting, which is needed for recovering missing arguments.We then introduce the bidirectional syntax, over which the bidirectional type system is defined.We then give the bidirectional typing rules and prove they are correct with respect to the declarative system.Finally, we conclude by showing the decidability of the bidirectional system for strongly-normalizing theories.

Matching modulo rewriting
Suppose we want to type @( , ) by first inferring the sort of , yielding .We know that the sort of the principal argument in the rule for @ is the pattern Tm(Π(A, .B{ })), so we could hope to recover and by matching against this pattern.However, because of the conversion rule, in dependent type theories we cannot expect to be syntactically equal to an instance of this pattern, but only convertible to it.Therefore, our goal is instead to find and satisfying Tm(Π(A, .B{ })) [ , .] ≡ .This shows that the process of recovering missing arguments in bidirectional typing is actually an instance of matching modulo rewriting -a connection that apparently had not been discussed before in the literature.This also explains why we were careful in Section 2.2 to require the sort of a constructor rule and the sort of the principal argument of a destructor rule to be patterns, as they need to support decidable and unitary matching.
In order to solve matching modulo problems, we define in Figure 6 an inference system which, given a pattern and a term , tries to compute a metavariable substitution v such that −→ * [v].
Here we write −→ h when −→ * and is head-normal, meaning that for all ′ with −→ * ′ , no rewrite rule can be applied to the head of ′ .Note that, because all of our rewrite rules are headed by destructors, all terms not of the form (t) are automatically head-normal.

P
. By induction on the matching judgment.
We then move to the converse of Proposition 4.1, stating that we can always find a substitution if is convertible to an instance of .

P
. By induction on the pattern, the only interesting case being when = (t).In this case, by applying confluence to (t[v]) ≡ we get (t[v]) −→ * ′ * ←− and because (t[v]) is head normal we have ′ = (u) with t[v] −→ * u.We conclude by applying the i.h. to t, which yields t ≺ u v ′ for some v ′ ≡ v, and allowing us to derive ≺ v ′ .
A direct consequence of soundness and completeness of matching is the following corollary, which will be useful in the proof of Proposition 4.4.
Finally, we establish that matching modulo is decidable when the expression from which we extract the substitution is strongly-normalizing (often abbreviated as s.n.), meaning that all reduction sequences issuing from are finite.

P 4.4 (D ).
• If is strongly-normalizing then ∃v.≺ v is decidable for all • If u is strongly-normalizing then ∃v.t ≺ u v is decidable for all t P .By induction on the pattern.We show the only interesting case, when = (t).Because is strongly-normalizing, we can use any reduction strategy to compute a head-normal form ′ for .
If ′ is not headed by then ∃v.≺ v cannot hold.Indeed, this would imply −→ * (u) for some u, so by confluence and the fact that (u) and ′ are head-normal we could then show that ′ is headed by , contradiction.
If ′ is of the form (u), then by i.h.we can decide ∃v.t ≺ u v.If this holds, then it follows that ∃v.≺ v holds.If ∃v.t ≺ u v does not hold, then ∃v.≺ v also does not hold.Indeed, if ∃v. ≺ v holds then we have −→ h (u ′ ) and t ≺ u ′ v ′ for some u ′ and v ′ .But from (u) ≡ (u ′ ) and confluence we get u ≡ u ′ , but Corollary 4.3 would then imply ∃v.t ≺ u v.
Remark 4.5.The condition of strong normalization in Proposition 4.4 could be slightly weaken to require only weak normalization, by instead employing in the proof a normalizing strategy, such as the maximal-outermost strategy [53,59].However, even if strategies derived from call-byvalue have weaker theoretical guarantees, they are generally easier to implement efficiently -for instance, by using normalization-by-evaluation, as in the case of our implementation.Moreover, most theories used in practice are either strongly-normalizing or not normalizing at all, and so it is questionable whether asking only for weak-instead of strong-normalization would bring any benefit in practice.

Bidirectional syntax
In order to define the bidirectional type system, we first have to address the problem that some terms without annotations cannot be algorithmically typed.Indeed, suppose for instance that we want to type the term @( ( .), ) by inferring the sort of the principal argument of @ to recover and .But because ( . ) is headed by a constructor, it can only be bidirectionally typed in mode check, so we are stuck.One could think that this limitation is specific to bidirectional typing, however a famous result by Dowek shows that, in a dependently-typed setting, the problem of typing unannotated terms is actually undecidable in its full generality [23].Therefore, instead of defining the bidirectional system over the regular syntax of terms, we will define it over the bidirectional syntax which, given a signature Σ, is defined by the following grammar.
By separating between checkable terms ∈ Tm c and inferrable terms ∈ Tm i we are now able to specify that the principal argument of a destructor can only be an inferable term, avoiding the situation described in the previous paragraph.The consequence of this is that terms of the form ( (t), u) are not directly part of the bidirectional syntax.Instead, we must first turn (t) into an inferable term by adding a (sort) ascription (t) :: , allowing us to then write ( (t) :: , u).The symmetric operation of embeding then allows us to create a checkable term from an inferable one .
Example 4.6.The inferrable and checkable terms for the signature Σ Π are given respectively by the following grammars, where we omit the scope information.
Because the bidirectional syntax requires us to add additional ascriptions when writing terms of the form ( (t), u), one can wonder if this requirement might be too inconvenient in practice.If we remove sort ascriptions from the bidirectional syntax, then for most theories (like T Π ) the checkable terms coincide exactly with the normal forms, and the inferable terms with the neutrals.As argued in other works [2,52], users of type theory almost never write redices, and because of this a large part of the bidirectional typing literature only supports the typing of normal forms [2-5, 21, 52], for which one needs no ascriptions.Our choice of also supporting ascriptions is simply a matter of giving users an extra convenience for the few situations in which writing a redex is more convenient, yet we expect that in most cases they will not be needed.Remark 4.7.Note that we have omitted metavariables from the bidirectional syntax.Even if metavariables are needed in the core syntax for specifying the theories in Section 2 (and the welltyped theories in Section 3), they are in general not needed for using the theories, and this is why they are in general omitted from most presentations of type theories.It is therefore reasonable to leave them out of the bidirectional syntax, as they would be of no utility for users.
Given ∈ Tm c or ∈ Tm i we write ∈ Tm (•) for its underlying term, obtained by forgetting the difference between checkable and inferable terms and by removing sort ascriptions.Similarly, if t ∈ MSub c we write t ∈ MSub (•) for its underlying metavariable substitution.

Bidirectional typing rules
Given a theory T, we can now define its bidirectional type system by the rules in Figure 7.The system is split in 4 judgments: • Γ ⊢ ⇐ sort : Checking that a checkable term is a well-formed sort.
Remark 4.8.The reader could argue that, for the fourth judgment, the most natural choice would be something of the form Γ ⊢ t ⇐ Θ.However, in some cases it will be necessary to check v. t : Ξ.Θ knowing already that v : Ξ holds, so our more general judgment allows us to prevent reverifying that v is well-typed a second time.
As in the declarative system, the most important rules are the one that instantiate the schematic typing rules: C , D and S .However, differently from the declarative system, no more guessing is needed when building a type derivation.For instance, when using rule D with ( , u) the omitted arguments are no longer guessed, but instead recovered by inferring the sort of the principal argument and then matching it against the associated pattern.
Example 4.9.Suppose we want to infer a sort for @( , ) in the theory T Π .To use rule D , we start by inferring a sort ′ for , and then we try to match it against the pattern Tm(Π(A, .B{ })).If matching succeeds, we recover the arguments and , which together with are then used in Γ | ( , ., . ) : (A : Ty, B{ : Tm(A)} : Ty, t{ : Tm(A)} : Tm(B)) ⊢ ( ) ⇐ (u : Tm(A)) By applying the rules that define the judgment Γ | v : Θ ⊢ t ⇐ Ξ, we see that this amounts to showing just Γ ⊢ ⇐ Tm( ), and so the final shape of this derivation is the following, which corresponds to the usual bidirectional rule for application.
It is also instructive to see what happens when type-checking a constructor.In this case, we first use matching to recover both the parameters t and indices t .With the parameters, we can then check the non-erased constructor arguments u.To conclude, we however also need to verify that the expected indices t correspond to the actual ones, by checking if v [t , u ] ≡ t holds.

Correctness of bidirectional typing
We now establish the correctness of the bidirectional type system with respect to the declarative typing rules of Section 3. In order to establish soundness, we will first need the following technical result for typing the arguments recovered through matching.It roughly states that, given a well-typed pattern such that the result of substituting v in is also well-typed, one can conclude that v is also well-typed -an implication that generally does not hold when is not a pattern.

P
. In order for the proof to go through, we show the following stronger statement.Let , and suppose moreover that Δ ⊢ v 1 : Θ 1 and that one of the following holds.
The proof is by induction on the pattern.
]], for some t and t ′ .We have so by Proposition 2.17 we get t In particular we have t ′ ≡ t [v], allowing us to apply the i.h. to conclude.
• Case = x{id Γ }, in which case we must have Θ 2 = x{Γ x } : x for some Γ x and x .By inversion on Θ; Γ ⊢ : we get ≡ x and Γ ≡ Γ x , and therefore Moreover, as the only metavariables of Θ appearing in Γ x and x are those of Θ 1 , we have sort.Now we can apply conversion and Proposition 3.9 to Then the result follows by hypothesis.
x ) By the i.h.applied to the first premises we get Δ ⊢ v 1 , v 2 : Θ 1 .Θ 2 .Then, note that we have , so by the i.h.applied to the second premises we get We can now show soundness:

P
. By induction on the derivation.
: , and because we have Γ ⊢ sort and ≡ we can apply the conversion rule to conclude Γ ⊢ : .• Case D .
Γ ⊢ :: ⇒ By the i.h.applied to the first premise we have Γ ⊢ sort.Now we can apply the i.h. to the second premise and conclude Γ ⊢ : , and because :: = we are done.
Γ ⊢ (t) ⇐ sort By well-typedness of the theory we have Ξ ⊢ and therefore we can apply the i.h. to show Γ ⊢ t : Ξ, from which we conclude Γ ⊢ ( t ) sort.
) By hypothesis we have Θ.Ξ, x{Δ} : ⊢, from which we get Θ.Ξ ⊢ and Θ.Ξ; Δ ⊢ sort.By the i.h.applied to the first premise we get Γ ⊢ v, t : Θ.Ξ, so by Proposition 3.8 applied with Θ.Ξ; Δ ⊢ sort we get Γ.Δ[v, t ] ⊢ [v, t ] sort.Now we can apply the i.h. to the second premise and get Γ.Δ[v, t ] ⊢ : [v, t ], from which we can conclude Γ ⊢ v, t , ì .

Annotability
. We now want to show that the bidirectional system is complete with respect to the declarative typing rules, however what notion of completeness should we consider?As argued by Dunfield and Krishnaswami [24], completeness in bidirectional typing should correspond to annotability: if Γ ⊢ : then for some ′ with ′ = we should have Γ ⊢ ′ ⇐ .In other words, ′ should be equal to modulo the insertion of sort ascriptions for when a destructor meets a constructor.Our proof of annotability will need the following lemma, ensuring that the bidirectional system respects conversion.L 4.12 (B ).

P
. By straightfoward induction, using Corollary 4.3 for cases C and D .
Our actual statement for annotability will be slightlier stronger than what we anticipated in the previous paragraphs.Let us call a bidirectional expression minimal if it contains no occurrences of :: or :: .Our theorem will not only ensure that a regular term can be annotated into a bidirectional one, but also that the resulting term is minimal.In the end of the subsection, this will allow us to derive an alternative completeness result as a corollary of Theorem 4.13.

P
. The proof is by induction on the derivation.For the rules V , C , D and C we need to show both points 1 and 2, and so we will organize these cases accordingly.
. By the i.h.applied to the first premise, for some u ′ ∈ MSub c |Γ| |Ξ | minimal we have Γ | t : Ξ ⊢ u ′ ⇐ Ξ and u ′ = u, and by Lemma 4.12 with t ≡ t ′ we have Moreover, by the i.h.applied to the second premise we get Finally, by inspection on the previous paragraph, ′ is not of the form ′′ , and so ′ :: ′ is indeed minimal We can then extract a strictly smaller derivation of Γ ⊢ : [t], so by i.h.we get ′ ∈ Tm i |Γ| minimal with Γ ⊢ ′ ⇒ ′ and ′ ≡ [t] and ′ = , and by Proposition 4.2 we get ≺ ′ t ′ with t ′ ≡ t.By the i.h.again we also get u ′ ∈ MSub c |Γ| |Ξ | minimal with Γ | t, ′ : (Ξ , x : ) ⊢ u ′ ⇐ Ξ and u ′ = u, so by Lemma 4.12 with t, ′ ≡ t ′ , ′ we have Γ | t ′ , : (Ξ , x : • Cases E MC or E MS where t = .Trivial.4.4.3Ascription-free completeness.When considering a bidirectional system with ascriptions, completeness is nicely expressed by the notion of annotability.However, as mentioned in Section 4.2, some authors prefer to leave ascriptions out of the bidirectional syntax, given that in most practical cases they are not much used.In this setting, completeness instead ensures that, if a bidirectional term (seen as a regular one) is typable by the regular type system, then it is also typable by the bidirectional one 4 .We now show that, when considering the subset of the bidirectional syntax which removes ascriptions, this form of ascription-free completeness can be deduced almost for free from Theorem 4.13.More precisely, let us say that a bidirectional expression is ascription-free if it contains no occurrence of :: .We will then show that, if Γ ⊢ : for a checkable ascription-free term, then Γ ⊢ ⇐ .Our main lemma for proving this will be the following one, stating that − satisfies a restricted form of injectivity.
is ascription-free and t ′ ∈ MSub c is minimal and t = t ′ then t = t ′ .

P
. By straightfoward induction on (or t) and case analysis on ′ (or t ′ ).
Ascription-free completeness now follows directly, by composing Theorem 4.13 with Lemma 4.14.

Decidability of bidirectional typing
We now come to the main property of interest of the bidirectional typing system: its decidability, allowing it to be used when implementing a type-checker for our theories.Our proof will need the following two lemmas, ensuring that matching and type-inference are functional, in the sense that when starting from convertible inputs we can only deduce convertible outputs.• By induction on or t.The only interesting case is when = (t), in which case we have −→ h (u) and t ≺ u v and ′ −→ h (u ′ ) and t ≺ u ′ v ′ .By applying confluence to (u) ≡ (u ′ ) we get u ≡ u ′ , allowing us to apply the i.h. to conclude v ≡ v ′ .A final hypothesis we will ask for ensuring the decidability of bidirectional typing is for the theory to be strongly-normalizing, meaning that Γ ⊢ : should imply that is s.n.-a direct consequence of this is that all with Γ ⊢ sort and t with Γ ⊢ t : Ξ must also be s.n.. Indeed, type-checking with dependent types requires checking the conversion of terms (in rules C and C ), whose decidability requires normalization.Moreover, strong normalization is also a requirement for the decidability of matching (Proposition 4.4).).Suppose that T is valid and s.n.
• If is checkable and Γ ⊢ sort then the statement Γ ⊢ ⇐ is decidable.
• If is checkable and Γ ⊢ then the statement Γ ⊢ ⇐ sort is decidable.

P
. We now proceed with the proof, which is by induction on the bidirectional expression.

MORE BIDIRECTIONAL TYPE THEORIES
In the previous sections we have illustrated our framework with the theory T Π , defining a basic Martin-Löf Type Theory with dependent products.We now show other examples of theories covered by our framework.All of the theories we present here are valid: our implementation can automatically check that all schematic rules are well-typed, and can also check that all but a few5 rewrite rules are type-preserving (the remaining rewrite rules can be shown to be type-preserving manually, using the same technique as in Example 3.5).Throughout this section, we use the informal notation for schematic typing rules discussed in Section 2.2 for readability purposes.We refer to the files of the implementation for more details about the examples.

Inductive types
Our framework supports the definition of arbitrary inductive types.For instance, starting from T Π , dependent sums can be defined by the following declarations.Note that, as one would wish, the parameters A and B are completely omitted in the constructor and the projections.A : Ty : Tm(A) ⊢ B : Ty t : Tm(Σ(A, .B{ })) proj 2 (t) : Tm(B{proj 1 (t)}) Dependent sums are an example of negative inductive types, which are types that are eliminated by means of projections.We can also define positive inductive types, which feature instead a dependent eliminator.The main example of positive inductive type is the W-type, which can be used to define any other positive inductive type [40].Once again, note how the parameters A and B are omitted from both the constructor sup and the eliminator rec W .

Universes
In dependent type theories, types can be reified as terms by adding universes.Starting from T Π , we define a Tarski-style universe by adding add a type U of codes and a decoding function El mapping each code to an associated type.We then must close U under the type formers of our theory, by adding the codes u for U and for Π, and stating that El decodes them to the expected types.For illustrative purposes, in the above we have defined a type-in-type universe, which is known to be inconsistent [20].This can however be easily solved if we stratify universes into an hierarchy, by instead introducing a family of symbols U , El , . . .indexed by some set ∈ L of universe levels.In particular, this allows us to define a Tarski-style variant of Pure Type Systems [13], which are usually presented using Russell-style universes.
Internal universe levels.By indexing the above symbols externally, they become annotated with levels in their names.A better approach is instead to index them internally, which then allows us to leverage our support for erased arguments.Let us illustrate this by taking L := N. We start by declaring a sort of levels along with constructors for zero and successor.We then update the definitions of U, El, u, in the following manner, so that they now take a level as an argument.With these definitions, we can omit the level annotations in El and .Note that in the case of u we cannot omit l from the syntax, otherwise we would not be able to define the rewrite rule El(u) ↦ −→ U(?).Cumulativity.For now, in the above theory we can only find a code decoding to Π(El( ), .El( )) if and live in the same universe.In order to fix this, we could define an heterogeneous version of allowing for and to be in different universes -see the file mltt-tarski-heterogeneous.bitts Tabareau show how to define a parametricity layer to isolate a consistent subset of the language, in which exceptions have to be caught locally.Nevertheless, if one wishes to use the theory for programming instead of proving theorems, it is reasonable to drop this extra layer and work in a language where all types are inhabited (like almost all commonly used programming languages).
Ex sort err : Ex A : Ty e : Ex raise(e) : Tm(A) We then must add rules for ensuring that destructors properly propagate the exceptions, such as the following one.@(raise(e), u) ↦ −→ raise(e) We can then extend the theory with generalized eliminators for the positive types in order to allow for exception-catching.For instance, supposing we also have extended the theory with booleans -and added the associated rule rec B (raise(e), .P{ }, pt, pf) ↦ −→ raise(e) for propagating exceptions -, we can add a new eliminator catch B in which raise is treated like a constructor of B, allowing us to handle the raised exception.This theory can then be extended with various types, and we refer to the file exceptional.bitts of the implementation for more details.
We can also interface the exceptional theory with a pure one by restricting the eliminators, in the spirit of the Multiverse Type Theory (MuTT) [46].For this, we redefine the theory by parametrizing Ty and Tm by a mode , which can either be P (for pure) or E (for exceptional).The raise constructor is then restricted to only allow for raising exceptions when in the exceptional mode, and the only way for eliminating from types in the exceptional mode to the pure world is by using catching eliminators, which then ensure that exceptions cannot be propagated.We refer to the file exceptional-multiverse.bitts of the implementation, where this approach is sketched.

Observational type theory
As our last example, we show how to define a variant of McBride et al's observational type theory (OTT) [9,57] in our framework.Starting from T Π , we begin by extending the theory with an heterogeneous equality type.The defining characteristic of OTT is that its equality Eq( , , ′ , ′ ) is defined inductively on the structure of the types and ′ .For instance, a proof of Eq(Π( , .), , Π( ′ , ′ .′ { ′ }), ′ ) should correspond exactly to a function mapping proofs of equality between and ′ to proofs of equality between @( , ) and @( ′ , ′ ).In the original formulation of OTT [9] this correspondence was made by adding a rewrite rule explaining how to reduce Eq(Π( , .), , Π( ′ , ′ .′ { ′ }), ′ ).
Here we instead adopt the approach taken by Atkey [12] and more recently by Pujet et al [58], in which one instead postulates symbols EqΠ and EqΠ for constructing and eliminating equality proofs between and ′ .Note that our support for omitting arguments is vital here to ensure that the numerous arguments do not get all recorded in the syntax.
Once the theory is specified, we can start writing and type-checking terms inside it.For instance, supposing we have also added a Tarski-style universe U, we can check the following definition of the polymorphic identity function.To type-check this definition, the tool first verifies that the sort given in the annotation is welltyped, and then type-checks the body of the definition against the sort.If all the steps succeed, the identifier is added to a global scope of top-level definitions and becomes available to be used in the rest of the file.
The implementation also supports local let definitions, as illustrated in the following example, which also shows how sort ascriptions can be used.Finally, we also provide commands for evaluating terms to normal form and asserting that two terms are definitionally equal.For instance, assuming we have defined factorial, we can use these commands to compute the factorial of 3 and check that it is equal to 6.The implementation also comes with many theories that can be defined in the framework, along with some examples of terms written in these theories.These can be found in the directory examples/, and most of them are discussed in Section 5.

The implementation
The core of the implementation can be separated into two main parts: the type-checking and the normalization algorithms.The type-checking algorithm follows very closely the bidirectional system described in Section 4 with only minor differences, so we will not discuss it here.
Regarding normalization, we have implemented it by employing an untyped variant of Normalization by Evaluation (NbE), inspired by the works of Coquand [21], Abel [1] and Kovacs [44].In NbE, terms are evaluated into a separate syntax of runtime values, in which binders are represented by closures and free variables by unknowns.This evaluation roughly corresponds to a call-by-value reduction to weak-head normal form.Values can then be compared for equality by entering closures and recursively evaluating and comparing their bodies.One of the benefits of this approach is that, by using de Bruijn indices in the syntax of regular terms but de Bruijn levels in the syntax of values, we completely avoid the need of implementing substitution or index-shifting functions, which are often complicated and inefficient.
Preliminary tests suggest that our implementation of normalization has good performances: we can compute factorial of 8 with unary natural numbers in around half a second, whereas the same test leads Coq to crash with a stack overflow and Agda to run for more than a minute before we terminate the process.In the future, we plan to further test the general performances of our tool with larger and more realistic examples.In particular, we would like to compare it with typecheckers for Dedukti [11,17].Because Dedukti has no support for erased arguments, its terms are highly-annotated, which can have an important impact on performance [28], whereas our support for non-annotated syntaxes should allow for shorter type-checking times.

RELATED WORK
Our general definition of dependent type theories draws much inspiration from other frameworks for type theory, such as GATs/QIITs [8,18,42], SOGATs [63], FTTs [39], and logical frameworks such as Dedukti [11,17] and Harper's Equational LF [36].However, we differ from these works by supporting non-annotated syntaxes and enforcing a constructor/destructor separation of symbols and rules, both of which seem to be important ingredients for bidirectional typing.
Another point of divergence from these frameworks is that most of them allow the use of arbitrary equations when defining the definitional equality of theories.However, it then becomes hard to give an implementation, as it would require deciding arbitrary equational theories.We instead take the approach of Dedukti of supporting only rewrite rules, which allows us to decide the definitional equality of theories in a uniform manner, and made it possible to implement our framework.A different approach is taken in Andromeda, an implementation of FTTs, where they also allow for extensionality rules [14].They however provide no proof of completeness for their equality-checking algorithm.
Our proposal also draws inspiration from the works of McBride, a main advocate of dependent bidirectional typing.His ongoing work on a framework for bidirectional typing [48,49] shares many similarities with ours, for instance by adopting a constructor/destructor separation of rules.However, an important difference with our framework is that he takes the bidirectional type system as the definition of the theory.Therefore, there is no discussion on how to show soundness and completeness with respect to a declarative system, as the bidirectional one is the only type system defined in his setting.This approach differs from most of the literature on dependent bidirectional typing [2-5, 24, 45], in which one first defines the type theory by a "platonic" declarative type system and then shows it equivalent to a bidirectional system which can be implemented.Finally, this choice also makes the metatheoretic study of theories quite different from what we have done here: for instance, even to be able to state subject reduction for the bidirectional system, the notion of reduction has to be updated to take ascriptions into account.
Another work from which ours drew inspiration is the one of Reed [60], where he proposes a variant of the Edinburgh Logical Framework in which arguments can be omitted.Crucially, these arguments are not elaborated through global unification, but instead locally recovered by annotating each declaration with modes to guide a bidirectional algorithm.However, his framework does not allow for extending the definitional equality, meaning that one cannot define dependent type theories with non-trivial equalities directly, but instead has to encode its derivations trees (as in [37]).This also means that his system does not need to deal with some complications that arise in our more general setting, such as matching modulo.
Finally, concurrently to our work, Chen and Ko [19] have proposed a framework for simplytyped bidirectional typing.They also define declarative and bidirectional systems and establish a correspondence between them.Compared to our work, their restriction to simple types removes many of the complexities that appear with dependent type theories.For instance, while their types are first-order terms with no notion of computation or typing, our sorts are higher-order terms considered modulo a set of rewrite rules and subject to typing judgments, making the process of recovering missing arguments much more intricate.The restriction to simple types also rules out examples like the ones presented in Section 5, given that they are all dependent type theories.They however provide an impressive formalization of all their results in Agda.

CONCLUSION AND FUTURE WORK
In this work we have given a generic account of bidirectional typing for a large class of dependent type theories.Our main results, Theorems 4.11 and 4.13, establish an equivalence between declarative and bidirectional type systems for a whole class of theories.The decidability of the bidirectional type system (Theorem 4.18) allowed for its implementation in the tool BiTTs, which has been used in practice with multiple theories.Compared to other theory-independent typecheckers, such as Dedukti and Andromeda, BiTTs' support for unannotated syntaxes can allow for better performances, making it a good candidate for cross-checking real proof libraries.
Regarding future work, the most important omission that we would like to address is that of type-directed equality rules, which are needed for handling -laws and definitional proof irrelevance.As mentioned in Section 7, our choice of supporting only rewrite rules was motivated by the fact that they allow for deciding the definitional equality in a uniform way, which made it possible to implement our framework.Indeed, as long as a rewrite system R is both confluent and strongly-normalizing, computing and comparing normal forms is a complete equality-checking algorithm, regardless of any other specificity of R. In contrast, even if it is well known how to design complete equality checking algorithms for specific theories with type-directed equalities [6], doing so in a general setting like ours seems to be an important challenge.We could take inspiration from the customizable equality-checking algorithm implemented in Andromeda [14].However, as mentioned in the previous section, their algorithm is not proven complete, so further research in this direction seems to be required.
Moreover, even if our system builds heavily on the constructor/destructor distinction in type theory, some theories employ equations that do not respect this separation.For instance, to define Russell universes we need the rewrite rule Tm(U) ↦ −→ Ty [62], which is not valid as Tm is not a destructor.Whether there is a way of accommodating these constructions without fully abandoning the constructor/destructor separation is something we would like to investigate in future work.
Finally, some could argue that our choice of declarative type system is not "declarative" enough, as some authors often prefer more abstract definitions for when specifying what is a type theory.For instance, the point of view that syntax should correspond to the initial model (for some notion of semantics) often leads one to consider fully-anotated terms with typed equality (or even quontiented terms [8]), whereas our declarative type system uses non-annotated terms and untyped equality.In the future, we would like to investigate if our results could be adapted to such a setting, for instance by considering a variant of Uemura's SOGATs [63] for the declarative type system.In this setting, our bidirectional system would be adapted into an elaboration algorithm, producing core fully-annotated syntax from the user-friendly bidirectional one -similarly to [33].

P 2 .
8 (U id).We have [id ] = and [id ] = for all ∈ Expr , and id [ ì ] = ì for all ì ∈ Sub , and id [v] = v for all v ∈ MSub .P .We first show [id ] = by induction on and id [ ì ] = ì by induction on .We then show [id ] = by induction on and id [v] = v by induction on .The following two properties are shown simultaneously.

L 4 .
14 (R − ).•If ∈ Tm c is ascription-free and ′ ∈ Tm c is minimal and = ′ then = ′ .• If ∈ Tm i is ascription-free and ′ ∈ Tm i is minimal and