Skip to content

Commit 3bcbf6b

Browse files
author
Dylan Just
committed
Progress.
1 parent efb8340 commit 3bcbf6b

3 files changed

Lines changed: 94 additions & 11 deletions

File tree

src/main/ts/Exercise3Optional.ts

Lines changed: 92 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -76,24 +76,106 @@ export const message = (e: Optional<string>): string =>
7676
(s) => "The value was " + s
7777
);
7878

79-
// TODO:
79+
// TODO: Implement a function using fold, that takes an Optional<number>. If it's some, double it. If it's none, return 0;
8080

81+
// TODO: Implement a function that takes an Optional<T> for any type T. Return true if it's some, and false if it's none.
82+
const trueIfSome = <T> (x: T): Optional<T> => {
83+
throw new Error("TODO");
84+
}
85+
86+
/*
87+
The last function you implemented is already part of the Optional type, and is called isSome().
88+
There's a corresponding isNone().
8189
90+
In some VERY LIMITED SITUATIONS you can use isSome() and then the UNSAFE getOrDie() function.
91+
It's acceptible to do this in tests, or where nested folding is incredibly cumbersome.
92+
*/
8293

94+
export const unsafeStuff = (e: Optional<string>): void => {
95+
if (e.isSome()) {
96+
console.log(e.getOrDie()); // AVOID
97+
}
98+
}
8399

84100
/*
85-
Aside: Constructing and Destructing
101+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
102+
+
103+
+ Aside: But you said we used "static" functions, not methods on objects!
104+
+
105+
+ Yeah, mostly we do. But Optional is from a time before we pushed that concept very hard.
106+
+ At some point, we intend to replace Optional's API with something fully static.
107+
+
108+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
109+
110+
111+
A common way to handle an Optional value is to provide a default value if in the case of none.
112+
113+
You can do this with fold, but getOrElse is a shortcut.
114+
*/
86115

87-
Many developers are familiar with the idea of a "constructor". You pass values into a constructor
88-
to construct an object. While we're not using TypeScript classes here, the functions "some" and
89-
"none" are still considered the constructors for the data type.
116+
// TODO: Using getOrElse, take an Optional<{age: string}> and turn it into an {age: string}, using a default value of 0.
90117

91-
What if you want to take an object and get its fields? Well, that's called "destruction". We're
92-
taking an object and destructing it into its constituent parts. You'll also find "destructuring assignment"
93-
as a feature of many languages, including TypeScript.
118+
// TODO: Write the same function using fold
94119

95-
Our "fold" function destructures the Option type. In category theory, "fold" is known as a "catamorphism".
96120

121+
/*
122+
Another way of thinking about an Optional, is that it's an array that contains either 0 or 1 elements.
123+
124+
Let's explore this by converting Optionals to and from Arrays.
97125
*/
98126

99-
// TODO: head over to Exercise3OptionTest to write some test cases for the above.
127+
// TODO: Write a function that converts an Optional<A> to an A[] for any type A.
128+
129+
// TODO: Write a function that converts an A[] to an Optional<A>. If the array has more than one element, only consider the first element.
130+
131+
132+
/*
133+
Well done! You've tackled the basis of Optionals. We'll dig into them a bit more in future exercises,
134+
but everything builds on what we've done here.
135+
136+
TODO: head over to Exercise3OptionTest to write some test cases for the above.
137+
138+
139+
140+
Below are some explanatory notes on some more advanced topics. Feel free to skip them if you're still learning.
141+
142+
143+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
144+
+
145+
+ Aside: TypeScript type refinement
146+
+
147+
+ Why can't we use type refinement to turn an Optional<T> to a Some<T> and make getOrDie() safe?
148+
+ It's to do with how we encode Optional. We use Church Encoding, so Optional is defined like this:
149+
+ interface Optional<A> {
150+
+ fold: <B> (ifNone: () => B, ifSome: (a: A) => B)
151+
+ }
152+
+
153+
+ whereas TypeScript encourages you to encode union types like this:
154+
+
155+
+ type None<A> = { kind: 'none' };
156+
+ type Some<A> = { kind: 'some', value: A };
157+
+ type Optional<A> = Some<A> | None<A>
158+
+
159+
+ Our Optional implementation predates TypeScript, so this wasn't an option at the time.
160+
+ That's not to say Church Encoding is bad. There are pros and cons, but that's a story for another day.
161+
+
162+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
163+
164+
165+
166+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
167+
+
168+
+ Aside: Constructing and Destructing
169+
+
170+
+ Many developers are familiar with the idea of a "constructor". You pass values into a constructor
171+
+ to construct an object. While we're not using TypeScript classes here, the functions "some" and
172+
+ "none" are still considered the constructors for the data type.
173+
+
174+
+ What if you want to take an object and get its fields? Well, that's called "destruction". We're
175+
+ taking an object and destructing it into its constituent parts. You'll also find "destructuring assignment"
176+
+ as a feature of many languages, including TypeScript.
177+
+
178+
+ Our "fold" function destructures the Option type. In category theory, "fold" is known as a "catamorphism".
179+
+
180+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
181+
*/

src/main/ts/Exercise4FP.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@ export const message3 = (e: Optional<string>): void => {
2828
console.log(m);
2929
}
3030

31+

src/test/ts/Exercise3OptionTest.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ UnitTest.test('toPositiveInteger', () => {
1717
// NOTE the examples above - due to how Optional is implemented, we can't compare values as JS objects/arrays/values,
1818
// and we need to pass in the tOption() equality value
1919

20-
});
20+
});

0 commit comments

Comments
 (0)