home *** CD-ROM | disk | FTP | other *** search
-
-
- Introduction to Gofer 11. USER-DEFINED DATATYPES AND TYPE SYNONYMS
-
-
- 11. USER-DEFINED DATATYPES AND TYPE SYNONYMS
-
- 11.1 Datatype definitions
- -------------------------
- In addition to the wide range of built-in datatypes described in
- section 7, Gofer also allows the definition of new datatypes using
- declarations of the form:
-
- data DatatypeName a1 ... an = constr1 | ... | constrm
-
- where DatatypeName is the name of a new type constructor of arity n>=0,
- a1, ..., an are distinct type variables representing the arguments of
- DatatypeName and constr1, ..., constrm (m>=1) describe the way in which
- elements of the new datatype are constructed. Each constr can take one
- of two forms:
-
- o Name type1 ... typer where Name is a previously unused constructor
- function name (i.e. an identifier beginning with a capital
- letter). This declaration introduces Name as a new constructor
- function of type: type1 -> ...-> typer -> DatatypeName a1 ... an.
-
- o type1 CONOP type2 where CONOP is a previously unused constructor
- function operator (i.e. an operator symbol beginning with a
- colon). This declaration introduces (CONOP) as a new constructor
- function of type: type1 -> type2 -> DatatypeName a1 ... an.
-
- [N.B. only the type variables a1, ..., an may appear in the type expressions
- in each constr in the definition of DatatypeName.]
-
-
- As a simple example, the following definition introduces a new type Day
- with elements Sun, Mon, Tue, Wed, Thu, Fri and Sat:
-
- data Day = Sun | Mon | Tue | Wed | Thu | Fri | Sat
-
- Simple functions manipulating elements of type Day can be defined using
- pattern matching:
-
- what_shall_I_do Sun = "relax"
- what_shall_I_do Sat = "go shopping"
- what_shall_I_do _ = "looks like I'll have to go to work"
-
- Another example uses a pair of constructors to provide a representation
- for temperatures which may be given using either of the centigrade or
- fahrenheit scales:
-
- data Temp = Centigrade Float | Fahrenheit Float
-
- freezing :: Temp -> Bool
- freezing (Centigrade temp) = temp <= 0.0
- freezing (Fahrenheit temp) = temp <= 32.0
-
- The following example uses a type variable on the left hand side of the
- datatype definition to implement a Set type constructor for
- representing sets using a list of values:
-
-
-
- 46
-
-
-
-
- Introduction to Gofer 11.1 Datatype definitions
-
-
- data Set a = Set [a]
-
- For example, Set [1,2,3] is an element of type Set Int, representing
- the set of integers {1, 2, 3} whilst Set ['a'] represents a singleton
- set of type Set Char. As this example shows, it is possible to use the
- same name simultaneously as both a type constructor and as a
- constructor function.
-
- Datatype definitions may also be recursive, using the name of the
- datatype being defined on the right hand side of the datatype
- definition (mutually recursive datatype definitions are also
- permitted). The following example is taken from the Haskell report [5]
- and defines a type representing binary trees with values of a
- particular type at their leaves:
-
- data Tree a = Lf a | Tree a :^: Tree a
-
- For example, (Lf 12 :^: (Lf 23 :^: Lf 13)) :^: Lf 10 has type Tree Int
- and represents the binary tree:
-
- ,--- 12
- ,--|
- | | ,--- 23
- | `--|
- | `--- 13
- --|
- `--- 10
-
- As an example of a function defined on trees, here are two definitions
- using recursion and pattern matching on tree valued expressions which
- calculate the list of elements at the leaves of a tree traversing the
- branches of the tree from left to right. The first definition uses a
- simple definition, whilst the second uses an `accumulating parameter'
- giving a more efficient algorithm:
-
- leaves, leaves' :: Tree a -> [a]
-
- leaves (Lf l) = [l]
- leaves (l:^:r) = leaves l ++ leaves r
-
- leaves' t = leavesAcc t []
- where leavesAcc (Lf l) = (l:)
- leavesAcc (l:^:r) = leavesAcc l . leavesAcc r
-
- Using the binary tree above as an example:
-
- ? leaves ((Lf 12 :^: (Lf 23 :^: Lf 13)) :^: Lf 10)
- [12, 23, 13, 10]
- (24 reductions, 73 cells)
- ? leaves' ((Lf 12 :^: (Lf 23 :^: Lf 13)) :^: Lf 10)
- [12, 23, 13, 10]
- (20 reductions, 58 cells)
- ?
-
-
-
-
-
- 47
-
-
-
-
- Introduction to Gofer 11.2 Type synonyms
-
-
- 11.2 Type synonyms
- ------------------
- Type synonyms are used to provide convenient abbreviations for type
- expressions. A type synonym is introduced by a declaration of the
- form:
-
- type Name a1 ... an = expansion
-
- where Name is the name of a new type constructor of arity n>=0, a1,
- ..., an are distinct type variables representing the arguments of Name
- and expansion is a type expression. Note that the only type variables
- permitted in the expansion type are those on the left hand side of the
- synonym definition. Using this declaration any type expression of the
- form:
-
- Name type1 ... typen
-
- is treated as an abbreviation of the type expression obtained from
- expansion by replacing each of the type variables a1, ..., an with the
- corresponding type type1, ..., typen.
-
- The most frequently used type synonym is almost certainly the String
- type which is a synonym for [Char]:
-
- type String = [Char]
-
- [ASIDE: This definition is actually built in to the Gofer system, but
- the effect is the same as if this declaration were included in the
- standard prelude.]
-
- Note that the types of expressions inferred by Gofer will not usually
- contain any type synonyms unless an explicit type signature is given,
- either using an explicitly typed expression (section 10.6) or a type
- declaration (section 9.12):
-
- ? :t ['c']
- ['c'] :: [Char]
- ? :t ['c'] :: String
- ['c'] :: String
- ?
-
- Unlike the datatype declarations described in the previous section,
- recursive (and mutually recursive) synonym declarations are not
- permitted. This rules out examples such as:
-
- type BadSynonym = [BadSynonym]
-
- And ensures that the process of expanding all of the type synonyms used
- in any particular type expression will always terminate. The same
- property does not hold for the illegal definition above, in which any
- attempt to expand the type BadSynonym would lead to the non-terminating
- sequence:
-
- BadSynonym ==> [BadSynonym] ==> [[BadSynonym]] ==> ....
-
-
-
-
- 48
-
-
-