@@ -24,9 +24,9 @@ So last time we looked at `Maybe`, which can be
24
24
25
25
``` typescript
26
26
const getHorse = (name : string ): Maybe <Horse > => {
27
- const found = goodHorses .find (horse => horse .name === name )
28
- return found ? just (found ) : nothing ()
29
- }
27
+ const found = goodHorses .find (horse => horse .name === name );
28
+ return found ? just (found ) : nothing ();
29
+ };
30
30
```
31
31
32
32
- ` nothing ` is all very well but it doesn't tell us why we are sitting here
@@ -38,20 +38,20 @@ const getHorse = (name: string): Maybe<Horse> => {
38
38
39
39
``` typescript
40
40
const getHorse = (name : string ): Horse => {
41
- const found = goodHorses .find (horse => horse .name === name )
41
+ const found = goodHorses .find (horse => horse .name === name );
42
42
if (! found ) {
43
- throw Error (` Horse ${name } not found ` )
43
+ throw Error (` Horse ${name } not found ` );
44
44
}
45
- return found
46
- }
45
+ return found ;
46
+ };
47
47
```
48
48
49
49
- ...and catch them down the line to see what happened.
50
50
51
51
``` typescript
52
- let maybeHorse
52
+ let maybeHorse;
53
53
try {
54
- maybeHorse = getHorse (" FAST-BOY" )
54
+ maybeHorse = getHorse (" FAST-BOY" );
55
55
} catch (e : string ) {
56
56
// do something with the Error
57
57
}
@@ -67,8 +67,7 @@ are out of disk space or memory.
67
67
## Enter, Either
68
68
69
69
``` typescript
70
- type Either <E ,A > = { type: " Left" , value: E }
71
- | { type: " Right" , value: A }
70
+ type Either <E , A > = { type: " Left" ; value: E } | { type: " Right" ; value: A };
72
71
```
73
72
74
73
- It represents any two outcomes, but usually...
@@ -83,7 +82,7 @@ type Either<E,A> = { type: "Left", value: E }
83
82
84
83
- ` Either ` and ` Result ` are semantically the same
85
84
86
- - If you wish to sound clever you can say they are ` isomorphic ` to one another.
85
+ - If you wish to sound clever you can say they are ` isomorphic ` to one another.
87
86
88
87
- This means you can swap between the two at will without losing any
89
88
information
@@ -95,20 +94,18 @@ type Either<E,A> = { type: "Left", value: E }
95
94
- ` Left :: E -> Either<E, never> `
96
95
97
96
``` typescript
98
- const left = <E >(value : E ): Either <E ,never > =>
99
- ({ type: " Left" , value })
97
+ const left = <E >(value : E ): Either <E , never > => ({ type: " Left" , value });
100
98
101
- left (" egg" )
99
+ left (" egg" );
102
100
// { type: "Left", value: "egg" }
103
101
```
104
102
105
103
- ` Right :: A -> Either<never, A> `
106
104
107
105
``` typescript
108
- const right = <A >(value : A ): Either <never ,A > =>
109
- ({ type: " Right" , value })
106
+ const right = <A >(value : A ): Either <never , A > => ({ type: " Right" , value });
110
107
111
- right (" leg" )
108
+ right (" leg" );
112
109
// { type: "Right", value: "leg" }
113
110
```
114
111
@@ -119,23 +116,23 @@ Now when something fails, we can say why
119
116
``` typescript
120
117
const divide = (dividend : number , divisor : number ): Either <string , number > => {
121
118
if (divisor === 0 ) {
122
- return left (" Cannot divide by zero" )
119
+ return left (" Cannot divide by zero" );
123
120
}
124
- return right (dividend / divisor )
125
- }
121
+ return right (dividend / divisor );
122
+ };
126
123
```
127
124
128
125
- When things go well...
129
126
130
127
``` typescript
131
- divide (10 ,2 )
128
+ divide (10 , 2 );
132
129
// { type: "Right", value: 5 }
133
130
```
134
131
135
132
- Or when they don't...
136
133
137
134
``` typescript
138
- divide (100 ,0 )
135
+ divide (100 , 0 );
139
136
// { type: "Left", value: "Cannot divide by zero" }
140
137
```
141
138
@@ -169,22 +166,20 @@ const horses: Horse[] = [
169
166
170
167
``` typescript
171
168
const getHorse = (name : string ): Either <string , Horse > => {
172
- const found = horses .filter (horse => horse .name === name )
173
- return found [0 ] ? right (found [0 ]): left (` Horse ${name } not found ` )
174
- }
169
+ const found = horses .filter (horse => horse .name === name );
170
+ return found [0 ] ? right (found [0 ]) : left (` Horse ${name } not found ` );
171
+ };
175
172
```
176
173
177
174
## Step 2 - Tidy Horse Name
178
175
179
176
- ` tidyHorseName :: Horse -> Horse `
180
177
181
178
``` typescript
182
- const tidyHorseName = (horse : Horse ): Horse =>
183
- ({
184
- ... horse ,
185
- name: horse .name .charAt (0 ).toUpperCase () +
186
- horse .name .slice (1 ).toLowerCase ()
187
- })
179
+ const tidyHorseName = (horse : Horse ): Horse => ({
180
+ ... horse ,
181
+ name: horse .name .charAt (0 ).toUpperCase () + horse .name .slice (1 ).toLowerCase ()
182
+ });
188
183
```
189
184
190
185
## Step 3 - Standardise Horse
@@ -199,30 +194,31 @@ type StandardHorse = {
199
194
type: " STANDARD_HORSE" ;
200
195
};
201
196
202
- type TailCheckError = { type: " HAS_NO_TAIL" }
203
- | { type: " TOO_MANY_LEGS" }
204
- | { type: " NOT_ENOUGH_LEGS" }
197
+ type TailCheckError =
198
+ | { type: " HAS_NO_TAIL" }
199
+ | { type: " TOO_MANY_LEGS" }
200
+ | { type: " NOT_ENOUGH_LEGS" };
205
201
```
206
202
207
203
- ` standardise :: Horse -> Either TailCheckError StandardHorse `
208
204
209
205
``` typescript
210
- const standardise = (horse : Horse ): Either <TailCheckError ,StandardHorse > => {
206
+ const standardise = (horse : Horse ): Either <TailCheckError , StandardHorse > => {
211
207
if (! horse .hasTail ) {
212
- return left ({ type: " HAS_NO_TAIL" })
208
+ return left ({ type: " HAS_NO_TAIL" });
213
209
}
214
210
if (horse .legs < 4 ) {
215
- return left ({ type: " NOT_ENOUGH_LEGS" })
211
+ return left ({ type: " NOT_ENOUGH_LEGS" });
216
212
}
217
213
if (horse .legs > 4 ) {
218
- return left ({ type: " TOO_MANY_LEGS" })
214
+ return left ({ type: " TOO_MANY_LEGS" });
219
215
}
220
216
return right ({
221
217
name: horse .name ,
222
218
hasTail: true ,
223
219
legs: 4 ,
224
220
type: " STANDARD_HORSE"
225
- })
221
+ });
226
222
};
227
223
```
228
224
@@ -232,10 +228,6 @@ const standardise = (horse: Horse): Either<TailCheckError,StandardHorse> => {
232
228
233
229
- Over to you...
234
230
235
- ## Great work.
236
-
237
- - You are very smart.
238
-
239
231
## Alternatives - a nice pattern
240
232
241
233
Our code here suggests a fairly linear path, but the truth is that most things
@@ -269,11 +261,12 @@ const otherHorses: Horse[] = [
269
261
- We could adapt this function to take the horse source as a parameter..
270
262
271
263
``` typescript
272
- const getHorse2 = (possibleHorses : Horse []) =>
273
- (name : string ): Either <string , Horse > => {
274
- const found = possibleHorses .filter (horse => horse .name === name )
275
- return found [0 ] ? right (found [0 ]): left (` Horse ${name } not found ` )
276
- }
264
+ const getHorse2 = (possibleHorses : Horse []) => (
265
+ name : string
266
+ ): Either <string , Horse > => {
267
+ const found = possibleHorses .filter (horse => horse .name === name );
268
+ return found [0 ] ? right (found [0 ]) : left (` Horse ${name } not found ` );
269
+ };
277
270
```
278
271
279
272
- But how do we try one and then the other?
@@ -285,6 +278,5 @@ const getHorse2 = (possibleHorses: Horse[]) =>
285
278
- Or indeed, for ` Maybe ` :
286
279
287
280
- ` alt :: Maybe A -> Maybe A -> Maybe A `
288
-
289
- - Let's try fixing our horse issues with these:
290
281
282
+ - Let's try fixing our horse issues with these:
0 commit comments