Algebraic type definitions
The simplest method of introducing a new data type into a Miranda script is by means of an algebraic type definition. This enables the user to introduce a new concrete data type with specified constructors. A simple example would be
tree ::= Nilt | Node num tree tree
The ::=' sign (pronounced
comprises) is always used to introduce an
algebraic data type. This definition introduces three new identifiers -
tree', a typename - Nilt
a nullary constructor of type tree (i.e. an
atomic tree) - and Node
, a constructor of type num->tree->tree->tree.
Now we can define a particular tree, using the constructors Nilt and
Node, for example
t = Node 3 Nilt Nilt
It is not necessary to have names for the selector functions because the constructors can be used in pattern matching. For example a function for counting the number of nodes in a tree could be written
size Nilt = 0
size (Node a x y) = 1 + size x + size y
Note that the names of constructors must begin with an upper case letter (and conversely, any identifier beginning with an upper case letter is assumed to be a constructor).
An algebraic type can have any number (>=1) of constructors and each
constructor can have any number (>=0) fields, of specified types. The
number of fields taken by a constructor is called its arity
. A
constructor of arity zero is said to be atomic. Algebraic types are a
very general idea and include a number of special cases that in other
languages require separate constructions.
One interesting case that all of the constructors can be atomic, giving
us what is called in PASCAL a scalar enumeration type
. Example
day ::= Mon|Tue|Wed|Thu|Fri|Sat|Sun
The union of two types can also be represented as an algebraic data type - for example here is a union of num and bool.
boolnum ::= Left bool | Right num
Notice that this is a labelled union type
(the other kind of union
type, in which the parts of the union are not distinguished by tagging
information, is not permitted in Miranda).
An algebraic typename can take parameters, thus introducing a family of
types. This is done be using generic type variables as formal
parameters of the ::=' definition. To modify our definition of
treeto allow trees with different types of labels at the nodes (instead of
all
num` as above) we would write
tree * ::= Nilt | Node * (tree *) (tree *)
Now we have many different tree types - tree num',
tree bool,
tree([char]->[char])', and so on. The constructors Node' and
Niltare both polymorphic, with types
tree and
->tree ->tree ->tree
*' respectively.
Notice that in Miranda objects of a recursive user defined type are not
restricted to being finite. For example we can define the following
infinite tree of type tree num
bigtree = Node 1 bigtree bigtree
Obsolete Language Features
Algebraic data types in Miranda originally (see Turner 1985) supported
two additional features, which have now been dropped from the definition
of the language. These are laws (equations on constructors written
using =>') and strictness annotations on fields in
::=` definitions
(written as ! following the field type).
The release-two compiler continues to support these features, so former
users of Miranda release one do not lose working programs at the change
to release two. However, they will eventually cease to be supported by
the Miranda compiler (sorry!). An obsolete feature
warning given at
each compilation of a script using them. A methodology for translating
out these features is given in the CHANGES section of this manual.
Laws and strictness annotations are no longer part of the Miranda language, and should not be taught to new users.
Reference: D. A. Turner ``Miranda: A Non-Strict Functional Language with Polymorphic Types'', Proceedings IFIP Conference on Functional Programming Languages and Computer Architecture, Nancy, France, September 1985 (Springer Lecture Notes in Computer Science 201:1-16).
this can be found at http://miranda.org.uk