Skip to content

Commit b52abfc

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

2 files changed

Lines changed: 106 additions & 6 deletions

File tree

src/main/ts/Exercise3Optional.ts

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,16 @@ Optional.from take a value which may be null, undefined or an actual value.
5252
- otherwise, it returns some() of the value
5353
5454
Optional.from is useful for taking values from the "nullable" world to the Optional world.
55+
56+
TODO: use Optional.from to implement the following DOM function
5557
*/
5658

57-
// TODO: use Optional.from to implement the following DOM function
5859
export const getNextSibling = (e: Element): Optional<ChildNode> => {
5960
throw new Error("TODO");
6061
};
6162

63+
// TODO: use Optional.from to implement a similar wrapper for Element.getAttributeNode(string)
64+
6265
/*
6366
How do we get data out of an Optional? Well, that's a bit tricky since there isn't always
6467
data in there! But, there's a way to do it and we call that function "fold".
@@ -129,17 +132,56 @@ Let's explore this by converting Optionals to and from Arrays.
129132
// 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.
130133

131134

135+
/*
136+
One of the most useful functions on Optional is "map". We say this function "maps a function over the Optional".
137+
138+
If the Optional is some, it runs the function over the some and returns the result as a "some".
139+
If the Optional. is none, it returns none.
140+
141+
Above, we talked about how an Optional is like an array restricted to 0 or 1 elements, so mapping over an Optional
142+
is very similar to mapping over an array (which we did in Exercise 2).
143+
144+
Some examples, then some exercises:
145+
*/
146+
147+
const x: Optional<string> = Optional.some(3).map((x) => String(x)); // returns Optional.some("3")
148+
149+
const y: Optional<string> = Optional.none<number>().map((x) => String(x)); // returns Optional.<string>none()
150+
151+
// TODO: Write a function that takes an Optional<number> and adds 3 to the number
152+
153+
// TODO: Write a function that takes an Optional<string> and prefixes the string with "hello"
154+
155+
// TODO: If the below function is called, does it return a value or throw an exception? Write your answer in a comment, and explain why you think it behaves this way?
156+
const willItKersplode = (): Optional<string> => {
157+
const z = Optional.none<string>();
158+
return z.map<string>((s) => {
159+
throw new Error("boom");
160+
});
161+
};
162+
132163
/*
133164
Well done! You've tackled the basis of Optionals. We'll dig into them a bit more in future exercises,
134165
but everything builds on what we've done here.
135166
136167
TODO: head over to Exercise3OptionTest to write some test cases for the above.
168+
*/
137169

138170

139-
171+
/*
140172
Below are some explanatory notes on some more advanced topics. Feel free to skip them if you're still learning.
141173
142174
175+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
176+
+ Aside: mapping
177+
+
178+
+ We've mapped over both Arrays and Optionals. A type that can be mapped over in this way
179+
+ is called a Functor. Arrays and Optionals are Functors. Functors are a very useful abstraction,
180+
+ but outside the scope of this tutorial.
181+
+
182+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
183+
184+
143185
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
144186
+
145187
+ Aside: TypeScript type refinement
@@ -173,9 +215,11 @@ Below are some explanatory notes on some more advanced topics. Feel free to skip
173215
+
174216
+ What if you want to take an object and get its fields? Well, that's called "destruction". We're
175217
+ 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.
218+
+ as a feature of many languages, including TypeScript. e.g. const { x } = { x: 3, y: 'foo' };
177219
+
178220
+ Our "fold" function destructures the Option type. In category theory, "fold" is known as a "catamorphism".
179221
+
180222
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
223+
181224
*/
225+

src/main/ts/Exercise4FP.ts

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,69 @@
1+
import { Option as Optional } from "@ephox/katamari";
2+
3+
/*
4+
Functional programming is about programming in functions. Functions in the mathematical sense. "Pure" functions.
5+
6+
A pure function is one that has no "side effects".
7+
1. It reads its arguments and returns a value.
8+
2. If you pass it the same input, it always produces the same output.
9+
3. It doesn't print anything to screen, send any network traffic, write to any databases.
10+
4. It doesn't mutate any state.
11+
12+
Anyone seeing this list for the first time will say: well what's the point of FP if I can't do those useful things?
13+
14+
Unfortunately, the answer is not satisfying to beginners: FP does have techniques to manage effects like these and
15+
still use pure functions, but we need to learn a few other things first. Also, these techniques are not well-suited
16+
to TypeScript.
17+
18+
Well, that's a bit of a let-down. But, there's a silver lining... a very, very shiny silver lining, and that's this:
19+
20+
*** You can do functional programming in limited situations and still reap a lot of the benefits. ***
21+
22+
So, we try to write our TypeScript in as functional way as is practical.
23+
24+
What are the benefits we're trying to get?
25+
- If functions only deal with their arguments and only return values, then they're easier to test.
26+
- By separating logic from effect, we structure our programs in a way that's easier to understand.
27+
- Pure functions are easier to refactor, as you don't have to worry about how many times you call them.
28+
- Pure functions in programming are the same as functions in math. When we use pure functions, we can make use of
29+
the mathematical properties of functions. It turns out that math has ... to put it mildly ... rather a lot to say about functions.
30+
31+
Now, for the sake of time, I'm not going to do any more hard-sell on why it's important - lots has already been written
32+
on this topic. For the rest of this exercise, we're just going to look at some of the basic techniques and common
33+
functions we use.
34+
*/
135

36+
/*
37+
Let's start with the simplest function there is: the identity function.
38+
It takes an argument and returns it.
39+
*/
40+
41+
const identity = <A> (a: A): A => a;
242

343
/*
4-
In functional programming, we aim to program
44+
You can find this function in katamari as Fun.identity.
45+
46+
Now, what use is that? I already had that value!
47+
48+
Well, let's go back to something we did in Exercise 3 - providing a default value. We used the getOrElse function
49+
on Optional. You can write a similar function like this:
50+
*/
51+
52+
const getOrElse1 = <A> (oa: Optional<A>, other: A): A =>
53+
oa.fold(
54+
() => other,
55+
(a) => a
56+
);
57+
58+
// Hang on - that looks familiar. The function we pass as the "some" case is the identity function.
59+
60+
// TODO: write a version of getOrElse1 using Fun.identity.
61+
562

663

7-
*/
864

965
// You can also use fold to do some kind of "side-effect" on each branch, as below.
10-
import { Option as Optional } from "@ephox/katamari";
66+
1167

1268
export const message2 = (e: Optional<string>): void =>
1369
e.fold(

0 commit comments

Comments
 (0)