Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Mutually Recursive Functions

import Lait
#lait

Normally, a definition in Lait can only refer to itself and to definitions that come before it. Sometimes, though, two (or more) functions need to call each other. To do this, we link the definitions together with the and keyword:

def isEven (n : Int) : Bool :=
  if n == 0 then true else isOdd (n - 1)
and isOdd (n : Int) : Bool :=
  if n == 0 then false else isEven (n - 1)

#eval isEven 10>> true
#eval isOdd 7>> true

Each clause after the first begins with and instead of def, and otherwise looks just like a named function. Every function in the group can call every other function in the group. Each function in a mutually recursive group must take at least one argument.

Mutually Recursive Types

Types can be mutually recursive too, using the same and syntax. Below, a Tree holds either a single value or a Forest of subtrees, and a Forest is a list of Trees:

type Tree<a> := | Leaf (v : a) | Node (c : Forest<a>)
and Forest<a> := | FNil | FCons (t : Tree<a>) (f : Forest<a>)

def treeSize (t : Tree<a>) : Int :=
  match t with
  | Leaf v => 1
  | Node c => forestSize c
  end
and forestSize (f : Forest<a>) : Int :=
  match f with
  | FNil => 0
  | FCons t f' => treeSize t + forestSize f'
  end

#eval treeSize (Node (FCons (Leaf 1) (FCons (Leaf 2) FNil)))>> 2