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
|
import {Option, fromNullable, matchW} from 'fp-ts/lib/Option';
// keep it simple
export type Account = string;
export interface Bank {
balance: (account: Account) => Promise<Option<number>>;
/// Deposit amount into account
///
/// This function increases the balance of the given account by the
/// specified amount. It's a `void` function hence implicitly
/// stateful: It's expected to change some internal state of the
/// implementing class.
///
/// @param account The account to deposit into
/// @param amt The amount to deposit
deposit: (account: Account, amt: number) => Promise<void>;
withdraw: (account: Account, amt: number) => Promise<void>;
}
export class SimpleBank implements Bank {
private accounts: Map<Account, number>;
constructor(accounts: Map<Account, number>) {
// clone the content of the map
this.accounts = new Map(accounts);
}
balance(account: Account): Promise<Option<number>> {
return Promise.resolve(fromNullable(this.accounts.get(account)));
}
deposit(account: Account, amt: number): Promise<void> {
const current = fromNullable(this.accounts.get(account));
matchW(
() => {
throw new Error(`Unknown account ${account}`);
},
(bal: number) => {
this.accounts.set(account, bal + amt);
},
)(current);
return Promise.resolve();
}
withdraw(account: Account, amt: number): Promise<void> {
const current = fromNullable(this.accounts.get(account));
matchW(
() => {
throw new Error(`Unknown account ${account}`);
},
(bal: number) => {
this.accounts.set(account, bal - amt);
},
)(current);
return Promise.resolve();
}
}
export type Operation = GetBalance | Withdraw | Deposit;
export type GetBalance = {op: 'GetBalance'; account: Account};
export type Withdraw = {op: 'Withdraw'; account: Account; amount: number};
export type Deposit = {op: 'Deposit'; account: Account; amount: number};
|