[EN] Bidirectional Type Checking

When you write a type checker, there are a few ways one might go about it.

First, you can do it outside-in: given an expression and a type, you check that the expression matches that type by inferring the type that the sub expressions should have, then checking that they do. This operation is typically called checking. Here, type information comes from the outside, and it flows into the expression.

For example, let's check that 3+x is an int. First, we realize that both 3 and x need to be int. Now we check that 3 is an int, and discover that it is. Then, we check that x is an int, and if it is, we would be done, and type checking would be successful. If not, then we'd emit a type error.

Second, you can do it inside-out: given an expression, you can infer types for the sub expressions, then use those to infer a type for the full expression. After that, you can check that the inferred type matches what you were expecting. This operation is typically called inference. Here, type information comes from inside the expression, and it flows out.

For example, let's infer a type for 3+x. First, we infer a type for the expression 3, and it turns out to be int. Then, we infer a type for the expression x (we probably just look this up in a symbol table). Then, since we are adding things, they should be of the same type, so we check that the two inferred types are the same. If they're not, we end with a type error, but if they are, we infer that the type of the entire expression is int.

These are fine on their own, but they struggle at different things, like function calls, anonymous functions, sub typing, etc. It turns out that by using checking on some types of expressions and inference on others, we can build more robust type checkers that avoid most of the pitfalls of either one. This idea is called bidirectional type checking.


About me

My name is Sebastian. I'm a competitive programmer (ICPC World Finalist) and coach. I also enjoy learning about programming language theory and computer graphics.

Social links:

Comments

  1. Thanks for the great introduction! I have a question. I keep reading that bidirectional typing is good at reporting errors precisely. Could you show an example where it does a better job than any other syntax directed system (e.g., HM) in reporting error?

    ReplyDelete

Post a Comment

Popular posts from this blog

[EN] Writing a Compiler is Surprisingly Easy (part 1)

[EN] Representing Programs Within Programs is Surprisingly Easy

[EN] Writing a Compiler is Surprisingly Easy (part 2)