-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathlesson1-option.ts
145 lines (118 loc) · 3.25 KB
/
lesson1-option.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
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
// everything you could possibly need to know about a Horse
export type Horse = {
type: 'HORSE'
name: string
legs: number
hasTail: boolean
}
// the type of a Horse that is pretty standard, all told
type StandardHorse = {
name: string
hasTail: true
legs: 4
type: 'STANDARD_HORSE'
}
// our extensive dataset of two (2) horses
export const standardHorses: Horse[] = [
{
type: 'HORSE',
name: 'CHAMPION',
legs: 3,
hasTail: false,
},
{
type: 'HORSE',
name: 'HOOVES_GALORE',
legs: 4,
hasTail: true,
},
]
// OK FUNCTIONS
// our somewhat basic horse getting function
const getHorse = (name: string) => {
let found
standardHorses.forEach((standardHorse) => {
if (standardHorse.name === name) {
found = standardHorse
}
})
return found
}
// a function that improves the formatting of a horse's name
// as it rightly deserves
const tidyHorseName = (horse: Horse): Horse => {
return {
...horse,
name: horse.name.toLowerCase(),
}
}
// a validation function to check whether a Horse can also
// be a StandardHorse
const mandatoryTailCheck = (
horse: Horse
): StandardHorse | undefined => {
if (!horse.hasTail || horse.legs !== 4) {
return undefined
}
return {
name: horse.name,
hasTail: true,
legs: 4,
type: 'STANDARD_HORSE',
}
}
// a naive reference implementation of a horse finding function
export const horseFinder = (name: string): string => {
const horse = getHorse(name)
const tidyHorse = horse ? tidyHorseName(horse) : undefined
const standardHorse = tidyHorse
? mandatoryTailCheck(tidyHorse)
: undefined
if (!standardHorse) {
return `${name} is not a good horse`
}
return `Found a good horse named ${standardHorse.name}`
}
/*
* Let's make the above more elegant and 10x
*
* first, we're going to need the following functions:
*/
type Option<A> = { type: 'Some'; value: A } | { type: 'None' }
// some :: A -> Option A
export const some = <A>(a: A): Option<A> => ({
type: 'Some',
value: a,
})
// none :: () -> Option never
export const none = (): Option<never> => ({ type: 'None' })
// FUNCTIONS THAT WE MIGHT WANT TO IMPLEMENT TO HELP US
// isSome :: Option A -> Boolean
export const isSome = undefined as any
// isNone :: Option A -> Boolean
export const isNone = undefined as any
// map :: (A -> B) -> Option A -> Option B
export const map = undefined as any
// orElse :: (A -> B) -> B -> Option A -> B
export const orElse = undefined as any
// join :: Option (Option A) -> Option A
export const join = undefined as any
// bind :: (A -> Option B) -> Option A -> Option B
export const bind = undefined as any
// THE NEW FUNCTIONS WE NEED TO WRITE
// newGetHorse :: String -> Option<Horse>
export const newGetHorse = undefined as any
// newMandatoryTailCheck :: Horse -> Option<StandardHorse>
export const newMandatoryTailCheck = undefined as any
// newHorseFinder :: String -> String
export const newHorseFinder = (name: string): string => {
const horse = newGetHorse(name)
const tidyHorse = horse ? tidyHorseName(horse) : undefined
const standardHorse = tidyHorse
? newMandatoryTailCheck(tidyHorse)
: undefined
if (!standardHorse) {
return `${name} is not a good horse`
}
return `Found a good horse named ${standardHorse.name}`
}