Some Background:

Gradual typing

Type systems that provide capability of controlling degree of static typing by annotating function parameters with types (or not) ([2])

Contracts

Lightweight form of gradual typing, enforcing types dynamically using assertions

  • Advantageous because you can implement contracts for untyped and typed languages as a library

Blame
Positive blame

The subject (function) does not satisfy a contract

Negative blame

The context (caller) does not respect a contract

Contracts

Example 1: First-Order Contract

f: int[> 9] -> int[0,99]

The contract compiler inserts code to check proper range of arguments and return values.

val rec f = λx. x + 100

If f’s result is not in the proper range, f is blamed itself (positive blame)

f 5

If x is not in the proper range on calling, f’s caller is blamed (negative blame).

Example 2: Higher-Order Functions

Higher-order function

Functions that accept others as arguments or yield functions as results

g: (int[> 9] -> int[0,99]) -> int[0,99]

g accepts int → int functions and must apply them to ints larger than 9, which must return ints between 0 and 99. g should accept functions without explicit contracts (g(λx.50)) and functions whose behavior depends on context. Key point in [3] is that contract checker waits until the higher-order procedure is applied, providing a witness to the contract violation enabling proper assignment of blame.

In [3], they create a Contract Calculus to how types and contracts interact.

sqrt contract

Blame

In [4], they combine notion of blame from Findler (see above) with gradual types from Siek and hybrid types from Knowles ([5]).

Alert: don’t ask me about this paper, because I want to read it still.

Intersection and Union Types

Intersection types
  • if a value has type \(S\) and \(T\), it can be assigned the intersection type \(S \cap T\)

  • Useful for encoding overloaded functions (see below), mixins, multiple inheritance

intersection types

Union types
  • a term of type \(S\) or \(T\) may be viewed as having type \(S \cup T\)

  • Useful for encoding uncertain data from branching code

  • A context that wants to use a value of union type \(S \cup T\) must be prepared to deal with both \(S\) and \(T\) because no way to distinguish

union types

Sidenote:

When we say "union types" here, we mean "non-disjoint union types", which are different from "disjoint union types."

Disjoint union types are: * sum type: set of values drawn from exactly two given types * variant type: labelled generalization of sums

An Example

function f(x) {
  if (typeof x === 'boolean') {
    if (x) return 'hello world'; else return !x;
  }
  return (x+10);
}

Here, the function \(f\) has type \(\text{Bool} \rightarrow (\text{String} \cup \text{Bool}) \cap (\text{Int} \rightarrow \text{Int})\).

Why Intersection and Union Types make Blame Hard

Sub-contracts can be violated without implying that a top-level contract was violated (i.e. contract can fail without necessarily causing an error). For example, caller of f can violate domain type in left branch of intersection if they satisfy domain type of right branch.

Their contributions

  1. Extend the untyped lambda calculus with contracts for monitoring higher-order intersection and union types, for the first time giving a uniform treatment to both.

  2. Define blame allocation for intersection and union that supports uniform monitoring rules, stratifying blame allocation into two phases: blame assignment and blame resolution.

  3. Providing a new definition of contract satisfaction in terms of blame behaviour.

Also Read:

[1] J. Williams, J. G. Morris, and P. Wadler, “The Root Cause of Blame: Contracts for Intersection and Union Types,” Proc. ACM Program. Lang., vol. 2, no. OOPSLA, pp. 134:1–134:29, Oct. 2018.

[2] J. G. Siek and W. Taha, “Gradual Typing for Functional Languages,” in In Scheme and Functional Programming Workshop, 2006, pp. 81–92.

[3] R. B. Findler and M. Felleisen, “Contracts for Higher-Order Functions,” in Proceedings of the Seventh ACM SIGPLAN International Conference on Functional Programming, 2002, pp. 48–59.

[4] P. Wadler and R. B. Findler, “Well-Typed Programs Can’t Be Blamed,” in Programming Languages and Systems, 2009, pp. 1–16.

[5] K. Knowles and C. Flanagan, “Hybrid Type Checking,” ACM Trans. Program. Lang. Syst., vol. 32, no. 2, pp. 6:1–6:34, Feb. 2010.

[6] P. Wadler, “A Complement to Blame,” 2015.

[7] M. Keil and P. Thiemann, “Blame Assignment for Higher-Order Contracts with Intersection and Union,” in Proceedings of the 20th ACM SIGPLAN International Conference on Functional Programming, 2015, pp. 375–386.