forked from enricopolanski/functional-programming
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path05_game.ts
89 lines (78 loc) · 1.82 KB
/
05_game.ts
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
// ====================
// GUESS THE NUMBER
// ====================
import * as T from 'fp-ts/lib/Task'
import * as O from 'fp-ts/lib/Option'
import { getLine, putStrLn } from './Console'
import { randomInt } from 'fp-ts/lib/Random'
import { between, ordNumber } from 'fp-ts/lib/Ord'
import { pipe } from 'fp-ts/lib/pipeable'
// il numero da indovinare
export const secret: T.Task<number> = T.fromIO(
randomInt(1, 100)
)
// combinatore: stampa un messaggio prima di una azione
function withMessage<A>(
message: string,
next: T.Task<A>
): T.Task<A> {
return pipe(
putStrLn(message),
T.chain(() => next)
)
}
// l'input è una stringa perciò dobbiamo validarlo
const isValidInteger = between(ordNumber)(1, 100)
function parseGuess(s: string): O.Option<number> {
const n = parseInt(s, 10)
return isNaN(n) || !isValidInteger(n) ? O.none : O.some(n)
}
const question: T.Task<string> = withMessage(
'Indovina il numero',
getLine
)
const answer: T.Task<number> = pipe(
question,
T.chain(s =>
pipe(
parseGuess(s),
O.fold(
() =>
withMessage(
'Devi inserire un intero da 1 a 100',
answer
),
a => T.task.of(a)
)
)
)
)
function check<A>(
secret: number,
guess: number,
ok: T.Task<A>,
ko: T.Task<A>
): T.Task<A> {
if (guess > secret) {
return withMessage('Troppo alto', ko)
} else if (guess < secret) {
return withMessage('Troppo basso', ko)
} else {
return ok
}
}
const end: T.Task<void> = putStrLn('Hai indovinato!')
// mantengo lo stato (secret) come argomento della funzione (alla Erlang)
function loop(secret: number): T.Task<void> {
return pipe(
answer,
T.chain(guess =>
check(secret, guess, end, loop(secret))
)
)
}
const program: T.Task<void> = pipe(
secret,
T.chain(loop)
)
program()