This repository was archived by the owner on Nov 6, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathch07
462 lines (304 loc) · 15.2 KB
/
ch07
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
Introduction to Gofer 7. BUILT-IN TYPES
7. BUILT-IN TYPES
An important part of Gofer is the type system which is used to detect
errors in expressions and function definitions. Starting with
primitive expressions such as numeric constants, Gofer assigns a type
to each expression that describes the kind of value represented by the
expression.
In general we write object :: type to indicate that a particular
expression has the indicated type. For example:
42 :: Int indicating that 42 is an integer (Int is the
name for the type of integer values).
fact :: Int -> Int indicating that "fact" is a function which
takes an integer argument and returns an
integer value (its factorial).
The most important property of the type system is that it is possible
to determine the type of an expression without having to evaluate it.
For example, the information given above is sufficient to determine
that fact 42 :: Int without needing to calculate 42! first.
Gofer has a wide range of built-in types, described in the following
sections. In addition, Gofer also includes facilities for defining new
types as well as types acting as abbreviations for complicated type
expressions as described in section 11.
7.1 Functions
--------------
If t1 and t2 are types then t1 -> t2 is the type of a function which,
given an argument of type t1 produces a result of type t2. A function
of type t1 -> t2 is said to have argument type t1 and result type t2.
In mathematics, the result of applying a function f to an argument x is
traditionally written as f(x). In many situations, these parentheses
are unnecessary and may be omitted when using Gofer.
e.g. if f :: t1 -> t2 and x :: t1 then f x is the result of applying
f to x and has type t2.
If t1, t2, ..., tn are type expressions then:
t1 -> t2 -> ... -> tn
can be used as an abbreviation for the type:
t1 -> (t2 -> ( ... -> tn) ...)
In a similar way, an expression of the form f x1 x2 ... xn is simply an
abbreviation for the expression ( ... ((f x1) x2) ... xn).
These two conventions allow us to deal with functions taking more than
one argument rather elegantly. For example, the type of the addition
12
Introduction to Gofer 7.1 Functions
function (+) is:
Int -> Int -> Int
In other words, "(+)" is a function which takes an integer argument and
returns a value of type (Int -> Int). For example, "(+) 5" is the
function which takes an integer value n and returns the value of the
integer n plus 5. Hence "(+) 5 4", which is equivalent to "5 + 4",
evaluates to the integer 9 as expected.
7.2 Booleans
-------------
Represented by the type "Bool", there are two boolean values written as
"True" and "False". The standard prelude includes several useful
functions for manipulating boolean values:
(&&), (||) :: Bool -> Bool -> Bool
The value of the expression b && d is True if and only if both
b and d are True. If b is False then d is not evaluated.
The value of the expression b || d is True if either of b or d
is True. If b is True then d is not evaluated.
not :: Bool -> Bool
The value of the expression not b is the opposite boolean value
to that of b; not True = False, not False = True.
Gofer includes a special form of `conditional expression' which enables
an expression to select between two alternatives according to the value
of a boolean expression:
if b then t else f
is an expression which is equivalent to t if b evaluates to True, or to
f if b evaluates to False. Note that an expression of this form is
only acceptable if b is an expression of type Bool and if the types of
t and f are the same, in which case the whole expression also has that
type.
7.3 Integers
-------------
Represented by the type "Int", the integer type includes both positive
and negative integers such as -273, 0 and 383. Like many computer
systems, the range of integer values that can be used is restricted and
calculations using large positive or negative numbers may lead to
(undetected) overflow.
A wide range of operators and functions are defined in the standard
prelude for use with integers:
(+) addition.
(*) multiplication.
(-) subtraction.
13
Introduction to Gofer 7.3 Integers
(^) raise to power.
negate unary negation. An expression of the form "-x" is treated
as the expression "negate x".
(/) integer division.
div " "
rem remainder, related to integer division by the law:
(x `div` y)*y + (x `rem` y) == x
mod modulo, like remainder except that the modulo has the same
sign as the divisor.
odd returns True if argument is odd, False otherwise.
even returns True if argument is even, False otherwise.
gcd returns the greatest common divisor of its two arguments.
lcm returns the least common multiple of its two arguments.
abs returns the absolute value of its argument.
signum returns -1, 0 or 1 indicating that its argument is negative,
zero or positive respectively.
The less familiar operators are illustrated by the following
identities:
3^4 == 81, 7 `div` 3 == 2, even 23 == False
7 `rem` 3 == 1, -7 `rem` 3 == -1, 7 `rem` -3 == 1
7 `mod` 3 == 1, -7 `mod` 3 == 2, 7 `mod` -3 == -2
gcd 32 12 == 4, abs (-2) == 2, signum 12 == 1
7.4 Floating point numbers
---------------------------
Represented by the type "Float", elements of this type can be used to
represent fractional values as well as very large or very small
quantities. Such values are however usually only accurate to a fixed
number of digits and rounding errors may occur in some calculations
making significant use of floating point quantities. A numeric value
in an input expression will only be treated as a floating point number
if it either includes a decimal point such as 3.14159, or if the number
is too large to be stored as a value of type Int. Scientific notation
may also be used to enter floating point quantities; for example 1.0e3
is equivalent to 1000.0, whilst 5.0e-2 is equivalent to 0.05.
[N.B. floating point numbers are not included in all implementations of
Gofer].
7.5 Characters
---------------
Represented by the type "Char", elements of this type represent
individual characters such as those entered at a keyboard. Character
values are written as single characters enclosed by apostrophe
characters: e.g. 'a', '0', 'Z'. Some special characters must be
entered using an `escape code'; each of these begins with a backslash
character '\', followed by one or more characters to select the
required character. Some of the most useful escape codes are:
'\\' backslash
'\'' apostrophe
'\"' double quote
14
Introduction to Gofer 7.5 Characters
'\n' newline
'\b' or '\BS' backspace
'\DEL' delete
'\t' or '\HT' tab
'\a' or '\BEL' alarm (bell)
'\f' or '\FF' formfeed
Additional escape characters include:
'\^c' control character, where c is replaced by
one of the characters:
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
For example, '\^A' represents control-A
'\number' representing the character with ASCII value
specified by the given decimal 'number'.
'\onumber' representing the character with ASCII value
specified by the given octal 'number'.
'\xnumber' representing the character with ASCII value
specified by the given 'hexadecimal' number.
'\name' named ASCII control character, where
`name' is replaced by one of the standard
ascii names e.g. `\DC3`.
In contrast with some common languages (such as C, for example)
character values are quite distinct from integers; however the standard
prelude does include functions:
ord :: Char -> Int
chr :: Int -> Char
which enable you to map a character to its corresponding ASCII value,
or from an ASCII value to the corresponding character:
? ord 'a'
97
(2 reductions, 6 cells)
? chr 65
'A'
(2 reductions, 7 cells)
?
7.6 Lists
----------
If a is a type then [a] is the type whose elements are lists of values
of type a. There are several ways of writing list expressions:
o The simplest list of any type is the empty list, written [].
o Non-empty lists can be constructed either by explicitly listing
the members of the list (for example: [1,3,10]) or by adding a
single element onto the front of another list using the (:)
15
Introduction to Gofer 7.6 Lists
operator (pronounced "cons"). These notations are equivalent:
[1,3,10] = 1 : [3,10] = 1 : 3 : [10] = 1 : 3 : 10 : []
(the (:) operator groups to the right so 1 : 3 : 10 : [] is
equivalent to (1:(3:(10:[]))) -- a list whose first element is 1,
second element is 3 and last element is 10).
The standard prelude includes a wide range of functions for
calculations involving lists. For example:
o length xs returns the number of elements in the list xs.
o xs ++ ys returns the list of elements in xs followed by the
elements in ys
o concat xss returns the list of elements in each of the lists in
xss
o map f xs returns the list of values obtained by applying the
function f to each of the values in the list xs in turn.
Here are some examples using these functions:
? length [1,3,10]
3
(15 reductions, 28 cells)
? [1,3,10] ++ [2,6,5,7]
[1, 3, 10, 2, 6, 5, 7]
(19 reductions, 77 cells)
? concat [[1], [2,3], [], [4,5,6]]
[1, 2, 3, 4, 5, 6]
(29 reductions, 93 cells)
? map ord ['H', 'e', 'l', 'l', 'o']
[72, 101, 108, 108, 111]
(22 reductions, 73 cells)
?
Note that all of the elements in a list must be of the same type, so
that an expression such as ['a', 2, False] is not permitted.
[ASIDE: At this point it might be useful to mention an informal
convention that is used by a number of functional programmers when
choosing names for variables representing elements of lists, lists
themselves, lists of lists and so on. If for example, a typical
element of a list is called x, then it is often useful to use the name
xs for a list of such values, suggesting that a list contains a number
of "x"s. Similarly, a list of lists might be called xss. Once you
have understood this convention it is much easier to remember the
relationship between the variables in the expression (x:xs) than it
would be if different names had been used such as (a:b).]
16
Introduction to Gofer 7.7 Strings
7.7 Strings
------------
A string is treated as a list of characters and the type String is
simply an abbreviation for the type [Char]. Strings are written as
sequences of characters enclosed between speech marks. All of the
escape codes that can be used for characters may also be used in a
string:
? "hello, world"
hello, world
(0 reductions, 13 cells)
? "hello\nworld"
hello
world
(0 reductions, 12 cells)
?
In addition, strings may contain the escape sequence "\&" which can be
used to separate otherwise ambiguous pairs of characters within a
string:
e.g. "\123h" represents the string ['\123', 'h']
"\12\&3h" represents the string ['\12', '3', 'h']
A string expression may be spread over a number of lines using a gap --
a non-empty sequence of space, tab and new line characters enclosed by
backslash characters:
? "hell\ \o"
hello
(0 reductions, 6 cells)
?
Notice that strings are printed differently from other values, which
gives the programmer complete control over the format of the output
produced by a program. The only values that Gofer can in fact display
on the terminal are strings. If the type of an expression entered into
Gofer is equivalent to String then the expression is printed directly
by evaluating and printing each character in the list in sequence.
Otherwise, the expression to be evaluated, e, is replaced by the
expression show' e where show' is a built-in function (defined as part
of the standard prelude) which converts any value to a printable
representation. The only way of printing a string value in the same
way as any other value is by explicitly using the show' function:
? show' "hello"
"hello"
(7 reductions, 24 cells)
?
The careful reader may have been puzzled by the fact the number of
reductions used in the first three examples above was zero. This is in
fact quite correct since these expressions are constants and no further
evaluation can be carried out. For constant expressions of any other
type there will always be at least one reduction needed to print the
17
Introduction to Gofer 7.7 Strings
value since the constant must first be translated to a printable
representation using the show' function.
Because strings are represented as lists of characters, all of the
standard prelude functions for manipulating lists can also be used with
strings:
? length "Hello"
5
(22 reductions, 36 cells)
? "Hello, " ++ "world"
Hello, world
(8 reductions, 37 cells)
? concat ["super","cali","fragi","listic"]
supercalifragilistic
(29 reductions, 101 cells)
? map ord "Hello"
[72, 101, 108, 108, 111]
(22 reductions, 69 cells)
?
7.8 Tuples and the unit type
-----------------------------
If t1, t2, ..., tn are types and n>=2, then there is a type of n-tuples
written (t1, t2, ..., tn) whose elements are also written in the form
(x1, x2, ..., xn) where the expressions x1, x2, ..., xn have types t1,
t2, ..., tn respectively.
e.g. (1, [2], 3) :: (Int, [Int], Int)
('a', False) :: (Char, Bool)
((1,2),(3,4)) :: ((Int, Int), (Int, Int))
Note that, unlike lists, the elements in a tuple may have different
types, although the number of elements in the tuple is fixed.
The unit type is written () and has a single element which is also
written as (). The unit type is of particular interest in theoretical
treatments of the type system of Gofer, although you may occasionally
find a use for it in practical programs.
18