• No results found

A type selection on type expressions

In document Decrypting Local Type Inference (Page 60-66)

3.3 Foundations of TypeFocus

3.3.1 A type selection on type expressions

With the visual interpretation of the TypeFocus abstraction, it becomes clear that the TypeFo- cus path is a list of individual type selectors, or edge selectors in the type expression tree. We distinguish 3 different kinds of TypeFocus selectors,φ, for our core language; one for each of the types and their type elements. The TypeFocus, denoted asΘ, is defined recursively as an empty path, or a concatenation of some TypeFocus selector and TypeFocus:

φ ::= φfun-param| φfun-res| φselx (type selector)

Θ ::= [ ] | φ::Θ (TypeFocus)

Similarly to list notation, theφ1 ::φ2::[ ] TypeFocus is equivalent to the shorter [φ1,φ2]

notation, for anyφ1andφ2.

When applied to any type the TypeFocus,Θ, is treated as a function of type

Θ : T → (T + (T × Θ)) (type extraction with TypeFocus)

We adopt the definition of sum and product types that is present in Pierce [2002]. The Type- Focus takes a type and returns a value of a sum type. The left (tagged) value of the sum type 46

3.3. Foundations of TypeFocus

contains the selected part of the input type, while the right (tagged) value is a product type of type and TypeFocus. Before we explain the reasons behind the unusual return type, we will first define complete semantics for the application of TypeFocus to types in Definition 4.

Definition 4 Semantics of TypeFocusΘ of type T → (T + (T × Θ)) for the core language.

([ ])(T ) = inlT (φfun-param::Θ)(T ) =  Θ(S) if T= ∀a.S → R inrT,φfun-param::Θ  else (φfun-res::Θ)(T ) =  Θ(R) if T= ∀a.S → R inrT,φfun-res::Θ  else (φselxi ::Θ)(T ) = ⎧ ⎨ ⎩ Θ (T i) if T = {x1: T1, ... , xn: Tn} and 1≤ i ≤ n inrT,φfun-res::Θ  else

The individual type selectorφfun-paramextracts the parameter type of a function type,φfun-res extracts the result type of a function type, andφselxi extracts the type of a member xi of a

record type.

Intuitively, the semantics of TypeFocus demand that if the type selection path is empty we return the identical type in a left tagged value. Since individual TypeFocus selectors,φ, are the elements of the path, the type selection attempts to apply them in sequence from left to right; if the head of the TypeFocus successfully selected the type, the resulting type is applied recursively to the tail of the type selection path until an empty TypeFocus is encountered or the internal structure of the type is different from the TypeFocus selector expectation. If an internal structure of the type is different, the application of TypeFocus returns the right tagged tuple consisting of the input type, and the TypeFocus instance.

For example,

• [φfun-res](A→ (B → C)) =inl(B→ C), the TypeFocus extracts a part of the input type

A→ (B → C).

• [φselz](A→ (B → C)) =inr



A→ (B → C),[φselz]



, the function type does not match the expected record type of the TypeFocus, and the application returns the failed right tagged tuple.

Similarly,

• [φfun-res,φfun-res](A→ (B → C)) =inlC , the TypeFocus extracts a part of the nested function type.

Chapter 3. Guided-analysis for type derivation trees

• [φfun-param,φselx,φfun-res](A→ (B → C)) =inr



A, [φselx,φfun-res]



, the extraction could only perform a partial type selection on the provided type.

Typically, type selection can be envisioned as a straightforward extractor function of type (T → T ). Our definition of TypeFocus allows us to deal gracefully with real examples when type selection fails to extract part of a type. Such failure happens when the input type does not conform to the type expected by the instance of TypeFocus. In the case of a type selection failure, the value of the product type consists of the part of the type on which selection failed, and of TypeFocus instance that could not perform the type selection on the remaining part of the type.

Under certain circumstances a failed type selection is not a sign of unsoundness, but in fact may be desired and reveal important typing properties. For example, our formulation of TypeFocus will allow us also to apply the same type selection to the type variables that have been instantiated or not. Let’s consider the TypeFocusΘ, whereΘ= [φfun-res,φfun-res,φselx],

and its application to some function type with instantiated type variableΘ({b⇒{x: B}}(b→

(I nt → b))) =inlB . The type extraction from the given type succeeds by returning the left tagged value. The application of the same TypeFocus to the same type, but with the abstract type variables, only partially selects part of the function type inΘ(∀b.(b → (Int → b))) = inr b, [φselx]



. In both cases we want to be able to apply the same type selection to the same type, modulo the type variable substitution.

Two TypeFocus values can be composed together using the ‘:::’ notation, i.e., Θ’ ::: Θ, for anyΘ’andΘ. The semantics of the composition intuitively define a concatenation of two

TypeFocus paths, which ensures thatΘis applied to the type that was first extracted in the Θ application if and only if the latter selection was successful, i.e., if the application ofΘ returned a left tagged value. Otherwise, it returns a failed right tagged tuple; the tuple consists of the part of the type that was extracted until a shape mismatch occurred inΘ selection, and a composition of Θ and the failed Θ instance. Similarly as in the list notation, the [φ1,φ2] ::: [φ3,φ4] concatenation is equivalent to the [φ1,φ2,φ3,φ4] notation for anyφ1,φ2,

φ3,φ4type selectors.

For example,

• ([φfun-res] ::: [φfun-res])(A→ (B → C)) =inlC . • ([φfun-param,φselx] ::: [φfun-res])(A→ (B → C)) =inr



A, [φselx,φfun-res]



, and the result represents only a partial type selection.

For convenience, Definition 5 defines an auxiliary functionΘtpeof type (T+ T × Θ) → T that takes the result of the application of TypeFocus and returns its type component, irrespective of whether it returned a left or right tagged value.

3.3. Foundations of TypeFocus

Definition 5 Extracting type selection from TypeFocus application. Θtpe(v) = case v of inlT ⇒ T inrT,Θ ⇒ T

To avoid ambiguous terms, throughout the rest of the work we use the following terminology for describing the analysis of type derivation trees:

• Conflicting types - refers to types that participate in a type mismatch where the type of the term fails to conform to the expected type.

• Source of the type - refers to the inference judgment where the given type is first intro- duced in the type derivation tree. For instance, in thefoldRightapplication analyzed in Figure 3.4, the source of the expected type Li st [⊥] in a type mismatch refers to the (app)inference judgment [?/

b]b,Γ wNil() :a⇒⊥Li st [a]?.

• Target type - refers to the type for which we want to find source(s) by analyzing the typ- ing decisions of the type derivation tree. When we say that a target type is represented by some TypeFocus instance, we mean that a type selection on some type corresponds semantically to that target type.

To help with the interpretation of TypeFocus type selection, we typically represent the extracted type component through a grayed-out selection on types on which TypeFo- cus is applied to.

For example, [φfun-param] applied to type∀a. a → Int extracts ∀a. a → Int

• Basic and complex TypeFocus - we classify a TypeFocus instance as a basic one if it is either [ ], [φfun-param], [φfun-res] or [φselx]. A complex TypeFocus instance consists of at

least two TypeFocus selectors i.e., the length of the type selection path is at least of size 2.

• Type inference rule of the type inference judgment - always refers to the last type infer- ence rule used in the given inference judgment.

The correlation between the nodes of derivation and TypeFocus

The analysis of type derivation trees can quickly become infeasible due to the amount of type information. To make it practical, our analysis will associate every node of the type derivation tree with a particular TypeFocus instance, thus reducing the typing information to a simple concept of type selection.

We illustrate the intuition behind such TypeFocus and type inference rule association using Figure 3.9. The figure summarizes the essential elements of the informal analysis of the

Chapter 3. Guided-analysis for type derivation trees

term prototype inferred type TypeFocus

Cons(x + 1) List[⊥] Li st [I nt ]  Li st[⊥] [ ]

fun((x, y)→Cons(x+ 1, y)) (Int, Li st [⊥]) → List[⊥] Undefined [φfun-res]

foldRight(xs)(Nil()) ? {b⇒Li st[⊥]}(((I nt , b)→ b ) → b) [φfun-param,φfun-res]

foldRight(xs) ? ∀b.b → (((Int,b) → b ) → b) [φfun-res,φfun-param,φfun-res]

Figure 3.9: Summary of the analysis of the type derivation tree forfoldRightapplication from Figure 3.4 leading to the source of type LIST[]. The columns represent the ele- ments of thew inference judgment (the environment is omitted). The TypeFocus value encapsulates the target type information at each node.

source of type LIST[]in thefoldRightfunction application (Figure 3.5 in Section 3.1) by listing all involvedw type inference judgments. Each row corresponds to the type deriva- tion tree node in a path from the conflicting types to the source of the inherited type. The last column reduces the target type information to TypeFocus instances.

The summary highlights how TypeFocus unifies type selection on prototypes up to the Prop- agation Root (the first two rows) with type selection on the inferred types for terms up to the source of type LIST[](the last two rows).

Since TypeFocus instances correspond to partial type information that is propagated at each node of the type derivation tree, the TypeFocus information can be further simplified to the following TypeFocus composition:

term type inference rule TypeFocus

Cons(x + 1) (app) Θ1= [ ]

fun((x, y)→Cons(x+ 1, y)) (abs) Θ2= φfun-res::Θ1

foldRight(xs)(Nil()) (app) Θ3= φfun-param::Θ2

foldRight(xs) (app) Θ4= φfun-res::Θ3

The summary reveals the relation between the incremental TypeFocus construction and prop- agation of partial type information in the rules that define the Local Type Inference.

The TypeFocus-based analysis - the intuition

With the semantics of TypeFocus explained, we are now in a position to illustrate its practical application on a non-trivial example that analyzes the decisions of the type inference rule, (app)(from Figure 2.4), that infers the type of function applications.

For the purpose of the example we can consider a fragment of the type derivation tree that inferred the type of a function application, say f (e), where (?,  w f (e) : {x : A→ B, y : C}). 50

3.3. Foundations of TypeFocus

We assume that the type of the function f has also been inferred in the (?, w f : ∀a. a → {x : a, y : C }) judgment, and let the inferred type variable substitution beσf (e), whereσf (e)=

[a⇒ (A → B)].

The example aims to explain the source of two different elements of the inferred type of the function application, represented by theΘf(e)TypeFocus:

Case Θf(e)= [φselx,φfun-res]:

The TypeFocus represents the target type B in the inferred type of function application be- causeΘf(e)({x : A→ B, y : C}) =inlB .

From the(app)type inference rule we know that:

1. The inferred type of function application is the same as the result type of the inferred type of the function (T in (?, w f: ∀a.S → T ) for some f) modulo the type variable substitution (we ignore the consequences of the adaptation for the moment). 2. The type variable substitution does not modify the components of types, except for

providing type instantiation for the abstract type variables.

This means that the type resulting from the application of theΘf(e)to the inferred type of the function application, and the type resulting from the application of theΘf(e)to the result type of the function, refer to the same type even though they might return different type values.

An application ofΘf(e)to the result type of the inferred function type of f givesΘf(e)({x : a, y : C })=inra, [φfun-res]



. The extracted type variable a reveals that in order to understand the origin of the target type B we have to find out howσf (e) type substitution, that instantiated

the type variable a, was inferred in the first place, but we do not have to continue the analysis of the premise that inferred the type of the function. In other words, we have found a desired source of the target type.

The function application node in the type derivation represents the source of the target type but it does not yet reveal how theσf (e)type substitution was inferred. That is why, the source

can be categorized as the intermediate one, and requires further analysis as we will explain later in the section. Intuitively, the failed TypeFocus, [φfun-res], will allow us continue the analysis of the inferred instantiation of the type variable since [φfun-res](σ(a)) =inlB still extracts the target type information.

Case Θf(e)= [φ sely]:

The TypeFocus represents the target type C in the inferred type of the function application becauseΘf(e)({x : A→ B, y : C}) =inlC .

Using the same argument as in the previous case, Θf(e)can be applied to the inferred re- sult type of the function, i.e., Θf(e)({x : a, y : C })=inlC . The extracted type, which is not a type variable, indicates that for locating the source of the target type, one can immediately

Chapter 3. Guided-analysis for type derivation trees

navigate to the node that inferred the type of the function, and ignore the type variable sub- stitution and the decisions that inferred the type of the argument e.

The analysis of the inferred type of the function, (?,  w f : ∀a. a → {x : a, y : C}), must not use the sameΘf(e)TypeFocus. The latter fails to represent the desired target type when ap- plied to the inferred type of the function, i.e., Θf(e)({x : A→ B, y : C}) =inlC but

Θf(e)(∀a. a → {x : a, y : C}) =inr∀a. a → {x : a, y : C}, Θf(e).

To derive rules for constructing TypeFocus instances that cross the boundaries of individual type inference rules, we look at the expected shape of the inferred types. In the case of the (app)rule, the inferred type of the function has to be a polymorphic function type. Therefore in order to provide a type selection that faithfully represents the initial target type informa- tion in the (?,  w f : ∀a. a → {x : a, y : C}) judgment, we append φfun-res toΘf(e)since (φfun-res::Θf(e))(∀a. a → {x : a, y : C}) =inlC , as desired.

With the above examples we have illustrated the construction and application of TypeFocus, The process is dependent only on the formal definition of the type inference rule, and yet can guide the navigation over the type derivation tree.

In document Decrypting Local Type Inference (Page 60-66)