Add exercise number 4 for Reader

This commit is contained in:
Hugo Saracino 2022-01-12 14:17:37 +01:00
parent 53440267bd
commit 662bf15c6d
3 changed files with 152 additions and 0 deletions

63
src/exo4/exo4.test.ts Normal file
View file

@ -0,0 +1,63 @@
import { Country, exclamation, greet, excitedlyGreet } from './exo4';
describe('exo4', () => {
describe('greet', () => {
it('should greet Alice in french', () => {
const result = greet('Alice')(Country.France);
expect(result).toStrictEqual('Bonjour, Alice');
});
it('should greet Bernardo in spanish', () => {
const result = greet('Bernardo')(Country.Spain);
expect(result).toStrictEqual('Buenos dìas, Bernardo');
});
it('should greet Crystal in english', () => {
const result = greet('Crystal')(Country.USA);
expect(result).toStrictEqual('Hello, Crystal');
});
});
describe('exclamation', () => {
it('should add exclamation in french style (with a space before "!")', () => {
const result = exclamation('Youpi')(Country.France);
expect(result).toStrictEqual('Youpi !');
});
it('should add exclamation in spanish style (between "¡" and "!")', () => {
const result = exclamation('Olé')(Country.Spain);
expect(result).toStrictEqual('¡Olé!');
});
it('should add exclamation in english style (with no space before "!")', () => {
const result = exclamation('Yeah')(Country.USA);
expect(result).toStrictEqual('Yeah!');
});
});
describe('excitedlyGreet', () => {
it('should excitedly greet Alice in french', () => {
const result = excitedlyGreet('Alice')(Country.France);
expect(result).toStrictEqual('Bonjour, Alice !');
});
it('should excitedly greet Bernardo in spanish', () => {
const result = excitedlyGreet('Bernardo')(Country.Spain);
expect(result).toStrictEqual('¡Buenos dìas, Bernardo!');
});
it('should excitedly greet Crystal in english', () => {
const result = excitedlyGreet('Crystal')(Country.USA);
expect(result).toStrictEqual('Hello, Crystal!');
});
});
});

88
src/exo4/exo4.ts Normal file
View file

@ -0,0 +1,88 @@
// `fp-ts` training Exercice 4
// Dependency injection with `Reader`
import { Reader } from 'fp-ts/Reader';
import { unimplemented } from '../utils';
// Sometimes, a function can have a huge amount of dependencies (services,
// repositories, ...) and it is often impractical (not to say truly annoying)
// to thread those values through multiple levels of the call stack.
//
// That's precisely what dependency injection is meant to solve, and it's not a
// concept exclusive to OOP!
// In the world of FP, the so-called `Reader` construct (just a fancy word for
// a partially applied function) offers precisely those capabilities.
///////////////////////////////////////////////////////////////////////////////
// SETUP //
///////////////////////////////////////////////////////////////////////////////
// Let's consider a small range of countries (here, France, Spain and the USA):
export enum Country {
France = 'France',
Spain = 'Spain',
USA = 'USA',
}
///////////////////////////////////////////////////////////////////////////////
// ASK //
///////////////////////////////////////////////////////////////////////////////
// These countries have different rules on how to add exclamation to a sentence:
// - french speakers will add an exclamation point at the end preceded by a
// space: "Youpi !"
// - spanish speakers begin the sentence with an inverted exclamation point and
// finish it by a regular one: `¡Olé!`
// - english speakers will have no space before the exclamation point at the end
// of the sentence: `Yeah!`
//
// The following function should take a sentence as input and return a `Reader`
// that will at some point expect a `Country` and return the sentence with the
// proper exclamation style.
//
// HINT: Take a look at `reader.ask` to access the environment value
export const exclamation: (sentence: string) => Reader<Country, string> =
unimplemented();
// Obviously, different countries often mean different languages and so
// different words for saying "Hello":
export const sayHello = (country: Country): string => {
switch (country) {
case Country.France:
return 'Bonjour';
case Country.Spain:
return 'Buenos dìas';
case Country.USA:
return 'Hello';
}
};
// Using the `sayHello` function above, write the `greet` function that
// delivers a personalized greeting to a person based on their name.
// The output should look something like `${hello}, ${name}`.
//
// HINT: Remember that a `Reader<R, T>` is just an alias for `(r: R) => T`
//
// HINT: You can look into `reader.map` to modify the output of a `Reader`
// action.
export const greet: (name: string) => Reader<Country, string> = unimplemented();
// Finally, we are going to compose multiple `Reader`s together.
//
// Sometimes, a simple greeting is not enough, we want to communicate our
// excitement to see the person.
// Luckily, we already know how to greet them normally (`greet`) and how to
// add excitement to a sentence (`exclamation`).
//
// Compose those two to complete the `excitedlyGreet` function below:
//
// HINT: As with other wrapper types in `fp-ts`, `reader` offers a way of
// composing effects with `reader.chain`.
export const excitedlyGreet: (name: string) => Reader<Country, string> =
unimplemented();

1
src/exo4/index.ts Normal file
View file

@ -0,0 +1 @@
export * from './exo4';