Skip to content

Commit

Permalink
feat: adds Do syntax for modules
Browse files Browse the repository at this point in the history
All modules now export bindTo and Bind
  • Loading branch information
waynevanson authored and gcanti committed Oct 30, 2020
1 parent 8b388b3 commit 9648e08
Show file tree
Hide file tree
Showing 11 changed files with 207 additions and 4 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions src/Observable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,27 @@ export {
*/
separate
}

/**
* @category Do
* @since 0.6.11
*/
export function bindTo<K extends string, A>(name: K): (fa: Observable<A>) => Observable<{ [P in K]: A }> {
return map(a => ({ [name]: a } as { [P in K]: A }))
}

/**
* @category Do
* @since 0.6.11
*/
export function bind<K extends string, A, B>(
name: Exclude<K, keyof A>,
f: (a: A) => Observable<B>
): (fa: Observable<A>) => Observable<{ [P in keyof A | K]: P extends keyof A ? A[P] : B }> {
return chain(a =>
pipe(
f(a),
map(b => ({ ...a, [name]: b } as any))
)
)
}
28 changes: 27 additions & 1 deletion src/ObservableEither.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { MonadObservable2 } from './MonadObservable'
import { Observable } from 'rxjs'
import { Task } from 'fp-ts/lib/Task'
import { getEitherM } from 'fp-ts/lib/EitherT'
import { pipeable } from 'fp-ts/lib/pipeable'
import { pipe, pipeable } from 'fp-ts/lib/pipeable'

const T = getEitherM(R.observable)

Expand Down Expand Up @@ -191,3 +191,29 @@ export {
*/
mapLeft
}

/**
* @category Do
* @since 0.6.11
*/
export function bindTo<K extends string, E, A>(
name: K
): (fa: ObservableEither<E, A>) => ObservableEither<E, { [P in K]: A }> {
return map(a => ({ [name]: a } as { [P in K]: A }))
}

/**
* @category Do
* @since 0.6.11
*/
export function bind<K extends string, E, A, B>(
name: Exclude<K, keyof A>,
f: (a: A) => ObservableEither<E, B>
): (fa: ObservableEither<E, A>) => ObservableEither<E, { [P in keyof A | K]: P extends keyof A ? A[P] : B }> {
return chain(a =>
pipe(
f(a),
map(b => ({ ...a, [name]: b } as any))
)
)
}
28 changes: 27 additions & 1 deletion src/ReaderObservable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import { Observable } from 'rxjs'
import { getReaderM } from 'fp-ts/lib/ReaderT'
import * as R from './Observable'
import { pipeable } from 'fp-ts/lib/pipeable'
import { pipe, pipeable } from 'fp-ts/lib/pipeable'
import { IO } from 'fp-ts/lib/IO'
import { Monad2 } from 'fp-ts/lib/Monad'
import { Monoid } from 'fp-ts/lib/Monoid'
Expand Down Expand Up @@ -258,3 +258,29 @@ export {
*/
separate
}

/**
* @category Do
* @since 0.6.11
*/
export function bindTo<K extends string, R, A>(
name: K
): (fa: ReaderObservable<R, A>) => ReaderObservable<R, { [P in K]: A }> {
return map(a => ({ [name]: a } as { [P in K]: A }))
}

/**
* @category Do
* @since 0.6.11
*/
export function bind<K extends string, R, A, B>(
name: Exclude<K, keyof A>,
f: (a: A) => ReaderObservable<R, B>
): (fa: ReaderObservable<R, A>) => ReaderObservable<R, { [P in keyof A | K]: P extends keyof A ? A[P] : B }> {
return chain(a =>
pipe(
f(a),
map(b => ({ ...a, [name]: b } as any))
)
)
}
32 changes: 31 additions & 1 deletion src/ReaderObservableEither.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { MonadObservable3 } from './MonadObservable'
import { MonadThrow3 } from 'fp-ts/lib/MonadThrow'
import { Bifunctor3 } from 'fp-ts/lib/Bifunctor'
import { getReaderM } from 'fp-ts/lib/ReaderT'
import { pipeable } from 'fp-ts/lib/pipeable'
import { pipe, pipeable } from 'fp-ts/lib/pipeable'
import { Observable } from 'rxjs'

/**
Expand Down Expand Up @@ -194,3 +194,33 @@ export {
*/
mapLeft
}

// DO

/**
* @category Do
* @since 0.6.11
*/
export function bindTo<K extends string, R, E, A>(
name: K
): (fa: ReaderObservableEither<R, E, A>) => ReaderObservableEither<R, E, { [P in K]: A }> {
return map(a => ({ [name]: a } as { [P in K]: A }))
}

/**
* @category Do
* @since 0.6.11
*/
export function bind<K extends string, R, E, A, B>(
name: Exclude<K, keyof A>,
f: (a: A) => ReaderObservableEither<R, E, B>
): (
fa: ReaderObservableEither<R, E, A>
) => ReaderObservableEither<R, E, { [P in keyof A | K]: P extends keyof A ? A[P] : B }> {
return chain(a =>
pipe(
f(a),
map(b => ({ ...a, [name]: b } as any))
)
)
}
34 changes: 34 additions & 0 deletions src/StateReaderObservableEither.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,3 +217,37 @@ export {
*/
mapLeft
}

// DO SYNTAX

/**
* @category Do
* @since 0.6.11
*/
export function bindTo<K extends string>(
name: K
): <S, R, E, A>(fa: StateReaderObservableEither<S, R, E, A>) => StateReaderObservableEither<S, R, E, { [P in K]: A }> {
return fa =>
pipe(
fa,
map(value => ({ [name]: value } as any))
)
}

/**
* @category Do
* @since 0.6.11
*/
export function bind<K extends string, S, R, E, A, B>(
name: Exclude<K, keyof A>,
f: (a: A) => StateReaderObservableEither<S, R, E, B>
): (
fa: StateReaderObservableEither<S, R, E, A>
) => StateReaderObservableEither<S, R, E, { [P in keyof A | K]: P extends keyof A ? A[P] : B }> {
return chain(a =>
pipe(
f(a),
map(b => ({ ...a, [name]: b } as any))
)
)
}
13 changes: 13 additions & 0 deletions test/Observable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as T from 'fp-ts/lib/Task'
import { identity } from 'fp-ts/lib/function'

import { observable as R } from '../src'
import { pipe } from 'fp-ts/lib/pipeable'

describe('Observable', () => {
it('of', () => {
Expand Down Expand Up @@ -206,4 +207,16 @@ describe('Observable', () => {
const t = await R.toTask(R.of(1))()
assert.deepStrictEqual(t, 1)
})

it('do notation', async () => {
const t = await pipe(
R.of(1),
R.bindTo('a'),
R.bind('b', () => R.of('b'))
)
.pipe(bufferTime(10))
.toPromise()

assert.deepStrictEqual(t, [{ a: 1, b: 'b' }])
})
})
12 changes: 12 additions & 0 deletions test/ObservableEither.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,4 +255,16 @@ describe('ObservableEither', () => {
assert.deepStrictEqual(e1, e2)
})
})

it('do notation', async () => {
const t = await pipe(
_.right(1),
_.bindTo('a'),
_.bind('b', () => _.right('b'))
)
.pipe(bufferTime(10))
.toPromise()

assert.deepStrictEqual(t, [E.right({ a: 1, b: 'b' })])
})
})
12 changes: 12 additions & 0 deletions test/ReaderObservable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,4 +298,16 @@ describe('ReaderObservable', () => {
const x = await _.run(pipe(_.of('a'), _.chainTaskK(f)), undefined)
assert.deepStrictEqual(x, 1)
})

it('do notation', async () => {
const t = await pipe(
_.of(1),
_.bindTo('a'),
_.bind('b', () => _.of('b'))
)(undefined)
.pipe(bufferTime(10))
.toPromise()

assert.deepStrictEqual(t, [{ a: 1, b: 'b' }])
})
})
13 changes: 13 additions & 0 deletions test/ReaderObservableEither.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,17 @@ describe('ReaderObservable', () => {
const x = await robe({})()
assert.deepStrictEqual(x, [E.right(1)])
})

// robe should expose right
it('do notation', async () => {
const t = await pipe(
ROBE.of(1),
ROBE.bindTo('a'),
ROBE.bind('b', () => ROBE.of('b'))
)(undefined)
.pipe(bufferTime(10))
.toPromise()

assert.deepStrictEqual(t, [E.right({ a: 1, b: 'b' })])
})
})
13 changes: 13 additions & 0 deletions test/StateReaderObservableEither.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,17 @@ describe('stateReaderObservableEither', () => {
const x = await srobe(2)()
assert.deepStrictEqual(x, [E.right(1)])
})

// should expose of
it('do notation', async () => {
const srobe = pipe(
SROBE.right(1),
SROBE.bindTo('a'),
SROBE.bind('b', () => SROBE.right('b')),
buffer
)

const x = await srobe('state')('reader')()
assert.deepStrictEqual(x, [E.right([{ a: 1, b: 'b' }, 'state'])])
})
})

0 comments on commit 9648e08

Please sign in to comment.