Skip to content

Commit 8978473

Browse files
committed
New Either exercises
1 parent c81b05d commit 8978473

File tree

4 files changed

+248
-190
lines changed

4 files changed

+248
-190
lines changed

slides/lesson2-either-tuple.md renamed to slides/lesson2-either.md

+43-51
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ So last time we looked at `Maybe`, which can be
2424

2525
```typescript
2626
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+
};
3030
```
3131

3232
- `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> => {
3838

3939
```typescript
4040
const getHorse = (name: string): Horse => {
41-
const found = goodHorses.find(horse => horse.name === name)
41+
const found = goodHorses.find(horse => horse.name === name);
4242
if (!found) {
43-
throw Error(`Horse ${name} not found`)
43+
throw Error(`Horse ${name} not found`);
4444
}
45-
return found
46-
}
45+
return found;
46+
};
4747
```
4848

4949
- ...and catch them down the line to see what happened.
5050

5151
```typescript
52-
let maybeHorse
52+
let maybeHorse;
5353
try {
54-
maybeHorse = getHorse("FAST-BOY")
54+
maybeHorse = getHorse("FAST-BOY");
5555
} catch (e: string) {
5656
// do something with the Error
5757
}
@@ -67,8 +67,7 @@ are out of disk space or memory.
6767
## Enter, Either
6868

6969
```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 };
7271
```
7372

7473
- It represents any two outcomes, but usually...
@@ -83,7 +82,7 @@ type Either<E,A> = { type: "Left", value: E }
8382

8483
- `Either` and `Result` are semantically the same
8584

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.
8786

8887
- This means you can swap between the two at will without losing any
8988
information
@@ -95,20 +94,18 @@ type Either<E,A> = { type: "Left", value: E }
9594
- `Left :: E -> Either<E, never>`
9695

9796
```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 });
10098

101-
left("egg")
99+
left("egg");
102100
// { type: "Left", value: "egg" }
103101
```
104102

105103
- `Right :: A -> Either<never, A>`
106104

107105
```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 });
110107

111-
right("leg")
108+
right("leg");
112109
// { type: "Right", value: "leg" }
113110
```
114111

@@ -119,23 +116,23 @@ Now when something fails, we can say why
119116
```typescript
120117
const divide = (dividend: number, divisor: number): Either<string, number> => {
121118
if (divisor === 0) {
122-
return left("Cannot divide by zero")
119+
return left("Cannot divide by zero");
123120
}
124-
return right(dividend / divisor)
125-
}
121+
return right(dividend / divisor);
122+
};
126123
```
127124

128125
- When things go well...
129126

130127
```typescript
131-
divide(10,2)
128+
divide(10, 2);
132129
// { type: "Right", value: 5 }
133130
```
134131

135132
- Or when they don't...
136133

137134
```typescript
138-
divide(100,0)
135+
divide(100, 0);
139136
// { type: "Left", value: "Cannot divide by zero" }
140137
```
141138

@@ -169,22 +166,20 @@ const horses: Horse[] = [
169166

170167
```typescript
171168
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+
};
175172
```
176173

177174
## Step 2 - Tidy Horse Name
178175

179176
- `tidyHorseName :: Horse -> Horse`
180177

181178
```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+
});
188183
```
189184

190185
## Step 3 - Standardise Horse
@@ -199,30 +194,31 @@ type StandardHorse = {
199194
type: "STANDARD_HORSE";
200195
};
201196

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" };
205201
```
206202

207203
- `standardise :: Horse -> Either TailCheckError StandardHorse`
208204

209205
```typescript
210-
const standardise = (horse: Horse): Either<TailCheckError,StandardHorse> => {
206+
const standardise = (horse: Horse): Either<TailCheckError, StandardHorse> => {
211207
if (!horse.hasTail) {
212-
return left({ type: "HAS_NO_TAIL" })
208+
return left({ type: "HAS_NO_TAIL" });
213209
}
214210
if (horse.legs < 4) {
215-
return left({ type: "NOT_ENOUGH_LEGS" })
211+
return left({ type: "NOT_ENOUGH_LEGS" });
216212
}
217213
if (horse.legs > 4) {
218-
return left({ type: "TOO_MANY_LEGS" })
214+
return left({ type: "TOO_MANY_LEGS" });
219215
}
220216
return right({
221217
name: horse.name,
222218
hasTail: true,
223219
legs: 4,
224220
type: "STANDARD_HORSE"
225-
})
221+
});
226222
};
227223
```
228224

@@ -232,10 +228,6 @@ const standardise = (horse: Horse): Either<TailCheckError,StandardHorse> => {
232228

233229
- Over to you...
234230

235-
## Great work.
236-
237-
- You are very smart.
238-
239231
## Alternatives - a nice pattern
240232

241233
Our code here suggests a fairly linear path, but the truth is that most things
@@ -269,11 +261,12 @@ const otherHorses: Horse[] = [
269261
- We could adapt this function to take the horse source as a parameter..
270262

271263
```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+
};
277270
```
278271

279272
- But how do we try one and then the other?
@@ -285,6 +278,5 @@ const getHorse2 = (possibleHorses: Horse[]) =>
285278
- Or indeed, for `Maybe`:
286279

287280
- `alt :: Maybe A -> Maybe A -> Maybe A`
288-
289-
- Let's try fixing our horse issues with these:
290281

282+
- Let's try fixing our horse issues with these:

src/lesson2-either-tuple.ts

-139
This file was deleted.

0 commit comments

Comments
 (0)