paper

A Practical Optional Type System for Clojure

  • Authors:

📜 Abstract

Dynamic programming languages often abandon the advantages of static type checking in favour of their characteristic convenience and flexibility. Static type checking eliminates many common user errors at compile-time that are otherwise unnoticed, or are caught later in languages without static type checking. A recent trend is to aim to combine the advantages of both kinds of languages by adding optional static type systems to languages without static type checking, while preserving the idioms and style of the language. This dissertation describes my work on designing an optional static type system for the Clojure programming language, a dynamically typed dialect of Lisp, based on the lessons learnt from several projects, primarily Typed Racket. This work includes designing and building a type checker for Clojure running on the Java Virtual Machine. Several experiments are conducted using this prototype, particularly involving existing Clojure code that is sufficiently complicated that type checking increases confidence that the code is correct. For example, nearly all of algo.monads, a Clojure Contrib library for monadic programming, is able to be type checked. Most monad, monad transformer, and monadic function definitions can be type checked, usually by adding type annotations in natural places like function definitions. There is significant future work to fully type check all Clojure features and idioms. For example, multimethod definitions and functions with particular constraints on the number of variable arguments they accept (particularly functions taking only an even number of variable arguments) are troublesome. Also, there are desirable features from the Typed Racket project that are missing, such as automatic runtime contract generation and a sophisticated blame system, both which are designed to improve error messages when mixing typed and untyped code in similar systems. Overall, the work described in this dissertation leads to the conclusion that it appears to be both practical and useful to design and implement an optional static type system for the Clojure programming language.

✨ Summary

Summary

The dissertation presents Typed Clojure, an optional static type checker for JVM Clojure intended to preserve common dynamic-language idioms. Its design is primarily adapted from Typed Racket and combines bidirectional checking, local type inference, occurrence typing, union and intersection types, singleton types, polymorphism, heterogeneous map types, variable-arity polymorphism, and specialized support for Java interoperability. The system is implemented as a library that analyzes Clojure abstract syntax trees and checks namespaces using programmer annotations at natural definition boundaries.

The evaluation demonstrates that the prototype can type-check substantial examples involving Java reflection, sequence-processing idioms, monadic abstractions, monad transformers, and some highly polymorphic code. The results are mixed: most of algo.monads can be checked, while the red-black-tree experiment causes the prototype to hang and the conduit port requires substantial simplification. The dissertation identifies multimethods, even-numbered variable-arity functions, records, runtime contracts, blame tracking, and portability to other Clojure dialects as important unresolved problems.

The work directly led to later research on Typed Clojure. The author’s research record identifies a subsequent peer-reviewed paper, Practical Optional Types for Clojure, published at ESOP 2016 with Rowan Davies and Sam Tobin-Hochstadt. (ambrosebs.com) A later dissertation, Typed Clojure in Theory and Practice, formalized additional features, proved a model type-sound, and evaluated Typed Clojure usage in more than 19,000 lines of real-world code. (thesis.ambrosebs.com) The implementation also continued as the open-source core.typed project and was subsequently moved to the typedclojure repository for newer Clojure versions. (github.com) These sources document clear continuation and implementation impact, but the available quick-search evidence does not establish broad influence on unrelated type-system research or sustained industry adoption beyond the Typed Clojure ecosystem.