summaryrefslogtreecommitdiff
path: root/miralib/manual/18
blob: d5cd0a4f6c2d40b08133bf332972c842be219b50 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
_B_a_s_i_c_ _t_y_p_e_ _s_t_r_u_c_t_u_r_e_ _a_n_d_ _n_o_t_a_t_i_o_n_ _f_o_r_ _t_y_p_e_s

The Miranda programming language  is  _s_t_r_o_n_g_l_y  _t_y_p_e_d  -  that  is  each
expression  and each variable has a type that can be deduced by a static
analysis of the program text.

_P_r_i_m_i_t_i_v_e_ _t_y_p_e_s
 num bool char

Values of type `num' include both integer and  floating  point  numbers,
e.g.
	23     0   -17   1.26e11
They  are  stored  using  different internal representations, but can be
freely mixed in calculations, and  are  both  of  type  `num'  for  type
checking  purposes.   There  is  automatic  conversion  from  integer to
floating point when required (but not in the opposite  direction  -  use
`entier', see standard environment).  Floating point numbers are held to
double precision, integers to unbounded precision.

The values of type `bool' are the two truth values:
	True    False

The values of type `char' are characters in the Latin-1  character  set,
e.g.
	'a'    '%'    '\t'

_L_i_s_t_ _t_y_p_e_s
 [t] is the type of lists whose elements are of type `t'

Thus [num] is the type of lists of numbers such as [1,2,3,4,5]

[[num]] is the type of lists of lists of numbers, such as [[1,2],[3,4]]

[char] are lists of characters  -  this  is  also  the  type  of  string
constants, so e.g. ['h','e','l','l','o'] and "hello" are interchangeable
objects of this type.

_T_u_p_l_e_ _t_y_p_e_s
 (t1,...,tn) is the type of a tuple with elements of type `t1' to `tn'

Example - the value (1,True,"red") is of type (num,bool,[char])

The type of the empty tuple, `()', is also  written  `()'.

Notice  that  tuples  are  distinguished from lists by being enclosed in
parentheses, instead of square brackets.

There is no concept of a 1-tuple, in Miranda, so the use of  parentheses
to  enclose  subexpressions,  as  in say a*(b+c), does not conflict with
their use for tuple formation.

_F_u_n_c_t_i_o_n_ _t_y_p_e_s
 t1->t2 is the type of a function with argument  type  `t1'  and  result
type `t2'

The '->' is right associative, so e.g.  `num->num->num' is the type of a
curried function of two numeric arguments.

In addition to the built-in types described above,  user  defined  types
may  be  introduced - these are of three kinds, synonym types, algebraic
types and abstract types - see separate manual entry for each.

_I_m_p_l_i_c_i_t_ _t_y_p_i_n_g
 In Miranda the types of identifiers do NOT normally need to be declared
explicitly  - the compiler is able to infer the type of identifiers from
their defining equations.  For example if you write
	plural x = x ++ "s"

the compiler will DEDUCE that `plural' is of type [char]->[char].  It is
however permitted to include explicit type declarations in the script if
desired, e.g.  you could write (anywhere in the same script)
	plural :: [char]->[char]

and the compiler will check  this  for  consistency  with  the  defining
equation  (the symbol `::' means `is of type').  More generally the type
declared may be an _i_n_s_t_a_n_c_e (see below)  of  the  type  implied  by  the
definition  -  in this case the effect of the declaration is to restrict
the type of the identifier to be less general than  it  would  otherwise
have been.

Note  that  only  top-level  identifiers  may  be  the  subject  of type
declarations, and that the type of an identifier may be declared at most
once in a given script.


_P_o_l_y_m_o_r_p_h_i_s_m
 The  final  feature  of  the type system is that it permits polymorphic
types.  There is an alphabet of generic type variables, written
	*    **    ***    etc.

each of which stands for an arbitrary type.  We give a simple example  -
the identity function, which may be defined
	id x = x

is attributed the type `*->*'.  This means that `id' has  many  types  -
`num->num', `char->char', `[[bool]]->[[bool]]' and so on - each of these
is an instance of its most general type, `*->*'.

Another simple example  of  polymorphism  is  the  function  `map'  (see
standard  environment)  which  applies  a function to every element of a
list.  For example `map integer [1,1.5,2]'  is  [True,False,True].   The
type of map is
	map :: (*->**) -> [*] -> [**]

The most polymorphic possible object is `undef',  the  identifier  which
stands  for  the  undefined,  or  error  value  (undef is defined in the
standard environment).  Since every type has  an  undefined  value,  the
correct type specification for undef is
	undef :: *

Many of the functions in the standard environment have polymorphic types
- the text of the standard environment (see separate  manual  entry)  is
therefore a useful source of examples.