A tiny interpreter in Elm that adds the zero? predicate and shows how Boolean values introduce runtime type errors.
ZERO builds on DIFF, where every expression evaluated to a number. With zero?, expressions can now produce either numbers or Booleans, so operations must check whether the values they receive are suitable for them.
Read ZERO: Adding Booleans and Runtime Type Errors to a Tiny Interpreter in Elm for a guided explanation of how it works.
flowchart TD
A["zero?(-(1, 1))"] -->|parse| B["Program (Zero (Diff (Const 1) (Const 1)))"]
B -->|evaluate| C["VBool True"]
You’ll need Nix with flakes enabled.
Enter the development environment and start the Elm REPL:
nix develop
elm replThen run the interpreter:
import ZERO.Interpreter as I
I.run "zero?(-(1, 1))"
-- Ok (VBool True)ZERO supports the constant and difference expressions from DIFF:
123-(456, 123)and adds the zero? predicate:
zero?(0)zero?(-(1, 1))zero? evaluates its operand and produces a Boolean:
zero?(0)
→ true
zero?(1)
→ falseBooleans can be produced by evaluation, but ZERO has no Boolean literals. true and false cannot be written directly as programs.
Before ZERO, every expression evaluated to a number. Adding Boolean values means an operation can now receive a kind of value it doesn't know how to use.
For example:
zero?(zero?(0))The inner zero? produces a Boolean, but the outer zero? expects a number.
Similarly:
-(zero?(0), 1)produces a Boolean where difference expects a number.
These programs are syntactically valid, but evaluation fails with a runtime type error.
ZERO represents runtime type errors with the types an operation expected and the types it actually received:
TypeError
{ expected = [ TNumber ]
, actual = [ TBool ]
}ZERO is part of Tiny Interpreters, where we learn how programming languages work by building tiny interpreters.