Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions exercises/reader.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import * as Read from './reader'
import * as R from 'fp-ts/Reader'
import * as M from 'fp-ts/Monoid'

describe('reader', () => {
it('one', () => {
expect(Read.one([R.of(1), R.of(2), R.of(3)])(true)).toEqual(6)
expect(Read.one([])(true)).toEqual(0)
})
it('two', () => {
expect(
Read.two([R.of(1), R.of(2), R.of(3)], M.monoidSum)(true)
).toEqual(6)
expect(Read.two([], M.monoidSum)(true)).toEqual(0)

const reader2 = Read.two(
[R.of(1), R.of(2), R.of(3), (a: number) => a + 1],
M.monoidProduct
)
expect(reader2(10)).toEqual(66)
expect(reader2(-1)).toEqual(0)
})
it('three', () => {
const reader = Read.three(
a => b => `${a} + ${b}`,
(rA: number) => rA * 2,
(rB: number) => rB * 3
)
expect(reader(0)).toEqual('0 + 0')
expect(reader(2)).toEqual('4 + 6')
})
it('four', () => {
const translationsEnglish = {
greeting: 'Good morning',
happyBirthday: 'Happy birthday',
genericPleasantry: 'Have a nice day',
}
const reader = Read.four('Mr Horse', new Date('2020-01-01'))
expect(
reader({
translations: translationsEnglish,
date: new Date('2020-01-01'),
})
).toEqual('Good morning, Mr Horse! Happy birthday!')
expect(
reader({
translations: translationsEnglish,
date: new Date('2021-02-01'),
})
).toEqual('Good morning, Mr Horse! Have a nice day.')

const translationsItalian = {
greeting: 'Buongiorno',
happyBirthday: 'Buon compleanno',
genericPleasantry: 'Buona giornata',
}
expect(
reader({
translations: translationsItalian,
date: new Date('2020-01-01'),
})
).toEqual('Buongiorno, Mr Horse! Buon compleanno!')
expect(
reader({
translations: translationsItalian,
date: new Date('2021-02-01'),
})
).toEqual('Buongiorno, Mr Horse! Buona giornata.')
})
})
54 changes: 54 additions & 0 deletions exercises/reader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import * as R from 'fp-ts/Reader'
import * as M from 'fp-ts/Monoid'
import { pipe } from 'fp-ts/function'
import * as A from 'fp-ts/Apply'

// given an array of Reader values, return one return value with all the values
// inside summed
export const one = <R>(
as: R.Reader<R, number>[]
): R.Reader<R, number> => pipe(as, M.fold(R.getMonoid(M.monoidSum)))

// given an array of Reader values, and a Monoid that knows how to combine the
// values, return a single Reader value with all the contents combined
export const two = <R, A>(
as: R.Reader<R, A>[],
monoid: M.Monoid<A>
): R.Reader<R, A> => pipe(as, M.fold(R.getMonoid(monoid)))

// given a function shaped `A` -> `B` -> `C`, a Reader<A> and a Reader<B>,
// return a Reader<C>
export const three = <R, A, B, C>(
f: (a: A) => (b: B) => C,
readerA: R.Reader<R, A>,
readerB: R.Reader<R, B>
): R.Reader<R, C> => pipe(readerA, R.map(f), R.ap(readerB))

type Env = {
translations: {
greeting: string
happyBirthday: string
genericPleasantry: string
}
date: Date
}

const thingOne = (name: string) => ({ translations }: Env) =>
`${translations.greeting}, ${name}!`

const thingTwo = (birthday: Date) => ({ date, translations }: Env) =>
date.getMonth() == birthday.getMonth() &&
date.getDate() == birthday.getDate()
? `${translations.happyBirthday}!`
: `${translations.genericPleasantry}.`

// given the functions `thingOne` and `thingTwo`, combine them to make a
// function that creates a birthday greeting.
export const four = (
name: string,
birthday: Date
): R.Reader<Env, string> =>
pipe(
A.sequenceT(R.reader)(thingOne(name), thingTwo(birthday)),
R.map(([a, b]) => `${a} ${b}`)
)