Tickets

Details

Hindley-Milner type systems (e.g. in Haskell 98) may be specified by rules deriving the type of an expression from those of its constituents, providing a simple way to reason about the types of expressions.
The rules may also be used as a bottom-up procedure for inferring principal types, with inferred types matched against any signatures supplied, but many other traversals yield the same answer.
A mixture of bottom-up inference and top-down checking often produces more informative error messages.

Bidirectional type inference

For arbitrary-rank types, a particular bidirectional traversal is specified by the type rules (see Fig. 8 on p25 of ​the arbitrary-rank paper), to make use of programmer-supplied annotations.
In particular,

functions and expressions with type signatures are checked top-down.

parameter variables without explicit signatures are assigned monotypes in upwards inference, but may inherit arbitrary-rank types in downwards checking.

in an application (whether inferred or checked), the type of the function is inferred bottom-up, and the argument checked top-down against the inferred argument type.

The generalization preorder must be recursively defined, with contravariance for -> types (see Fig. 7 on p22 of
​the arbitrary-rank paper).

The system has the following properties:

Programs containing no foralls are typeable if and only if they are typeable in Haskell 98.

Inference produces principal types, though checking may accept more types.

Both checking and inference are monotonic with respect to the generalization preorder.

Boxy types

Boxy types generalize bidirectional inference, and also allow impredicative types (type variables may be instantiated to polytypes, and polytypes may occurs as arguments of type constructors).

Pros

Cons

More complex than Rank2Types, which cover the most common cases (and can encode the rest, though clumsily).

No clear programmer-level description of the restrictions that apply.
To quote the ​boxy-types paper:

The type system is arguably too complicated for Joe Programmer to understand, but that is true of many type systems, and perhaps it does not matter too much: in practice, Joe Programmer usually works by running the compiler repeatedly, treating the compiler as the specification of the type system. Indeed, a good deal of the complexity of the type system (especially Section 6) is there to accommodate programs that "ought" to work, according to our understanding of Joe's intuitions.