Type checking is a compiler phase that verifies expressions have valid types before evaluation, using a typing judgment where the left side (expression and environment) determines the right side (type); the type checker validates constants (bool/int), variables (environment lookup), and binary operators (operand type matching) by recursively checking sub-expressions and raising errors for type mismatches or unbound variables.
OCaml Type Checker Implementation Tutorial | Static Type Checking
Added:next up we should actually implement pipe checking so type checking goes in the chain here between parsing and evaluation after we parse and get an ast out we're going to type check that ast before we go ahead with evaluation so i've added type checking to the pipeline here of course now i need to actually write a type checking function okay so i've started off implementing the type checking function here by writing a specification for it type check e is just going to be e if e type checks successfully in other words it's just going to return its argument as long as it's possible to give that argument of type and more particularly what that means is that in the empty static environment there must exist a type t such that e has type t type check is going to raise failure with some unspecified string if e does not type check so to implement type check we're going to need to implement that typing relation let's do that with a function called type of okay let's pause here i've created a function type of and the spec for that function is that type of n e is the type of e in environment n that is it's the t such that m shows that e has type t so think of the input of this function as everything to the left of the colon in the typing judgment and the output of the function as everything to the right of the colon in the typing judgment now to use that function type of as part of type check i need to call typeof on the expression e in the empty environment now for environments i have a choice of how to implement them obviously they are maps from identifiers to names and the easiest implementation of map is either going to be as an association list or using the standard library's built-in map functor let's play it easy here and use association lists of course the empty list then is the empty environment let's return to the spec of type check it's supposed to return the expression e right now it's not doing that it's returning the type of that expression that's what typeof returns so we need to fix that so we'll compute the type of the expression and then return that expression assuming we've got to type back now what should typeof do if it doesn't manage to find a type let's say that it will also raise failure so that actually means from the perspective of type check we don't care what that type t is all we care about is the type of succeeds without raising an exception if it does succeed we're going to just throw away that type in fact you can see the yellow underline there that's a value t that is never used in the rest of that function so i could write let underscore equal type of empty to solve that problem to get rid of that warning or i could do this that is i could ignore the result of type checking just run it for its side effects for raising an exception and then return e let's start implementing typeof okay let's pause here having just implemented one branch of it so far if the expression e is a boolean constant either true or false then its type must be t bool that's what our type checking rule said so we'll return t bool for that at this point it's clear i could use the function syntactic sugar next i need to implement all the other type checking rules let's do them a few at a time we know that integer constants will have type t int and we know that when we find a variable name we're supposed to look it up in the static environment and return whatever we find there if we don't find a binding for that variable name then we have an unbound variable error and that's a type checking error at this point so we need to implement that let's push this off into a helper function for looking up variables in an environment so i've implemented my helper function for lookup now in terms of a function from the standard library i will raise uh unbound variable error if the variable name is not bound in that back down here in type of of course i need to change that variable name to x there are now two places in this interpreter where unbound variable error is getting raised one of them is during type checking and the other is during evaluation now during type checking we're going to reject any program that would have an unbound variable error but we still have to have this pattern match case down here in the evaluator because at run time it is a theoretical possibility from ocam's perspective that there could be an unbound variable error just because there could be a var constructor here we know though that we're never going to reach this point because of type checking nonetheless we have to have this branch in the pattern match here otherwise it would be inexhaustive so we leave it in knowing that type checking will prevent it i'm going to introduce two new exception types so that i can disambiguate whether i get this exception for unbound variables at runtime that is during eval or at compile time that is during type checking so i've added two new exception constructors and two convenience functions for raising both of those now i can go through the rest of my code and disambiguate whether i'm getting a type checking error or a runtime error now is this strictly necessary no of course not i could have done all of this just by raising failure but this helps make it a little clearer what the errors are that's resulting from my interpreter okay so having finished up patching up all of those now i can return to implementing type of okay let's pause here i know that my implementation of the binary operator type checking rule is going to be more than just a very short line of code so i've gone ahead and factored out a mutually recursive helper function for it as we had been doing for implementation of evaluation before here i want to match against the binary operator and the results of recursively type checking the sub expressions e1 and e2 in order to figure out whether the application of that operator is correct so to type check a binary operator there's only three of them add mult and less than or equal to each one of those have to has to take two integers as its arguments uh and returns the appropriate type an integer for add and bolt and a bool for less than or equal to be off error is this error message that i've defined up here above already which is the operator and operand type mismatch again that is something that could occur at type checking time and if so we'll catch it here and make sure that we raise an exception and never allow the rest of the program to be evaluated but down here as part of the evaluation it is also a possibility that it could occur at runtime now in theory our type checker will prevent this but ocamel in order for its pattern match exhaustiveness checker to be satisfied is going to need to have a branch here and so here we'll raise a runtime error for that binary operator
Up Next

The Simply Typed Lambda Calculus Explained | Introduction & Basics
@TheUBerlin
11.1K views•2021-11-18

BitTorrent Protocol Explained: Piece Selection & Peer Choking
@StevenGordonAU
481 views•2013-02-22

HM Type Inference: Constants and Names | OCaml Programming
@MichaelRyanClarkson
2.7K views•2021-08-08

Enigma Machine Mechanics: WWII Encryption Explained
@JaredOwen
13.2M views•2021-12-11
Related Study Plans & Knowledge Roadmaps
Structured learning paths in Computer Science



































![Building a Typechecker from scratch [1/20] Introduction to Type theory and checking](https://i.ytimg.com/vi/3nGBnXUGxaY/maxresdefault.jpg)


![OPLSS'24: Amal Ahmed [1/5]](https://i.ytimg.com/vi/64Gzpd5YDVo/maxresdefault.jpg)


![[POPL'18] Milner Award Lecture: The Type Soundness Theorem That You Really Want to Prove (...](https://i.ytimg.com/vi/Skh5wiSj1m8/maxresdefault.jpg)
