Skip to content

WIP reader #8

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
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}`)
)