# The mLite Type System

Types in mLite are bound to values rather than variables, and they
are checked dynamically at run time.

Primitive lists are heterogenous:

[ 1, "hello", #"x", true, 1.61, fn x=x ]

## Algebraic Types

Algebraic compound data types can be defined by the user:

type :tree = :leaf (x) | :node (:tree, :tree)

Constructors are used to build complex data structures:

:node (:node (:leaf 1, :leaf 2) ;; o
:node (:leaf 3, :leaf 4)) ;; / \
;; / \
;; o o
;; / \ / \
;; 1 2 3 4

Infix declaration turn constructors, like `:node`

, into
binary operators (here `:node`

gets the same precedence as
`::`

):

infix :node = ::

Infix operators simplify expressions syntax a lot:

(:leaf 1 :node :leaf 2) :node (:leaf 3 :node :leaf 4)

Even algebraic types are heterogenous:

(:leaf 1 :node "foo") :node (:leaf 3 :node :leaf [1,2,3])

However, they check their consistency, e.g. a `:node`

accepts only a tuple of `:tree`

's as its argument:

:node (:leaf 1, "oops") ;; THIS WON'T WORK, because "oops" is not a :tree

Functions are polymorphic, with a much greater flexibility than in
statically typed languages (at the expense of safety, of course).

For example, the `q`

function, below, computes the quotient
of two numbers when passed a tuple, and the reciprocal value when passed
a singular argument:

fun q (x, y) = x / y
| x = 1 / x

The `revnum`

function reverses a number:

fun revnum (0, b) = b
| (a, b) = revnum (a div 10, b * 10 + a mod 10)
| a = revnum (a, 0)

When applied to a single argument, it calls itself with a tuple
containing an accumulator (`b`). However, this is a technique
that is only useful for ad-hoc hacking, because it allows you to do
things like this (giving the unspecified result 98123):

revnum (123, 98)

So in production code, `revnum`

would look like this:

local
fun revn (0, b) = b
| (a, b) = revn (a div 10, b * 10 + a mod 10)
in
fun revnum a = revn (a, 0)
end

Pattern matching can be combined with guard
expressions and type predicates. The following function can be used
to compare any combination of characters, strings, or numbers, where
a type mismatch results in a `false`

result:

fun equals (a, b) where char a
= char b also a = b
| (a, b) where str a
= str b also a = b
| (a, b) where real a
= real b also a = b
| _ = false

However, the built-in `eql`

function should be used to do
this, because it covers all types of the mLite language.

contact