Discriminated unions provide a way to define new structured data types.
For example here's a couple of type definitions that represent very simple arithmetic expressions:
:- type expression ---> const(int)
; var(string)
; binaryOperation(expression,operator,expression).
:- type operator ---> add ; subtract.
These definitions specify arithmetic expression parts such as constants(
const
), variables(var
), binary operations(binaryOperation
), etc.Given these definitions we can instantiate them by calling the constructors:
main(!IO) :-
X = binaryOperation(var("x"),add,const(10)),
Also we can use Mercury's unification to easily manipulate them, for example the following function writes the content of the expression to the output:
:- func operator_to_string(operator) = string.
operator_to_string(add) = "+".
operator_to_string(subtract) = "-".
:- pred write_expression(expression::in,io::di,io::uo) is det.
write_expression(const(C),!IO) :-
io.write_int(C,!IO).
write_expression(var(S),!IO) :-
io.write_string(S,!IO).
write_expression(binaryOperation(Operand1,Operator,Operand2) ,!IO) :-
write_expression(Operand1,!IO),
io.write_string(operator_to_string(Operator),!IO),
write_expression(Operand2,!IO).
Calling this predicate like this:
main(!IO) :-
X = binaryOperation(var("x"),add,const(10)),
write_expression(X,!IO).
Generates:
x+10