Recursive (grammar, definitions)
allows grammar
to refer to type constructors from the mutually recursive definitions
. The definitions may also refer to each others' type constructors.
Ordinarily, grammar
itself is just a Tycon
argument, although technically it can be any grammar.
For example, the following definitions define a binary tree parameterized by a type stored at its leaves.
let defns =
[ { tycon = "tree"
; tyvars = ["a"]
; grammar =
Variant
{ name_kind = Capitalized
; clauses =
[ { name = "Node"
; args = Cons (Tycon ("node", [Tyvar "a"]), Empty)
}
; { name = "Tree"
; args = Cons (Tycon ("leaf", [Tyvar "a"]), Empty)
}
]
}
}
; { tycon = "node"
; tyvars = ["a"]
; grammar = List (Many (Tycon "tree", [Tyvar "a"]))
}
; { tycon = "leaf"
; tyvars = ["a"]
; grammar = [Tyvar "a"]
}
]
;;
Normally, the type of a tree storing integers would be written like this:
Recursive (Tycon ("tree", [ Integer ]), defns)
It is equivalent, though needlessly verbose, to replace the Tycon
reference with the grammar of "tree"
, substituting Integer
for Tyvar "a"
:
Recursive
( Variant
{ name_kind = Capitalized
; clauses =
[ { name = "Node"
; args = Cons (Tycon ("node", [Tyvar "a"]), Empty)
}
; { name = "Tree"
; args = Cons (Tycon ("leaf", [Tyvar "a"]), Empty)
}
]
}
, defns )