Skip to content

Commit f853ed2

Browse files
committed
feat(rx-utils): add sink2, update context2
1 parent 5771609 commit f853ed2

File tree

3 files changed

+73
-16
lines changed

3 files changed

+73
-16
lines changed

packages/rx-utils/src/context2.utils.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { Monad2 } from 'fp-ts/lib/Monad';
33
import { map as readerMap, Reader } from 'fp-ts/lib/Reader';
44
import { sequenceT } from 'fp-ts/lib/Apply';
55
import { Omit } from 'typelevel-ts';
6-
import { combineLatest, Observable } from 'rxjs';
76
import {
87
ProductLeft,
98
ProductMap,
@@ -12,11 +11,10 @@ import {
1211
import { deferReader } from '@devexperts/utils/dist/adt/reader.utils';
1312
import { pipe, pipeable } from 'fp-ts/lib/pipeable';
1413
import { memoOnce } from '@devexperts/utils/dist/function/memoize';
15-
import { eqShallow } from '@devexperts/utils/dist/typeclasses/eq/eq.utils';
1614
import { NonEmptyArray } from 'fp-ts/lib/NonEmptyArray';
1715
import { array } from 'fp-ts/lib/Array';
18-
import { URI as URIObservable } from 'fp-ts-rxjs/lib/Observable';
19-
import { instanceObservable } from './observable.utils';
16+
import { instanceSink, sink, Sink, URI as URISink } from './sink2.utils';
17+
import { strictEqual } from 'fp-ts/lib/Eq';
2018

2119
export const URI = '@devexperts/dx-utils//Context';
2220
export type URI = typeof URI;
@@ -26,14 +24,15 @@ declare module 'fp-ts/lib/HKT' {
2624
}
2725
}
2826

29-
export interface Context<E, A> extends Reader<E, Observable<A>> {}
27+
export interface Context<E, A> extends Reader<E, Sink<A>> {}
3028

31-
const memo = memoOnce(eqShallow);
32-
export const instanceContext: Monad2<URI> & ProductLeft<URI> & ReaderM1<URIObservable> = {
29+
const memo = memoOnce({
30+
equals: strictEqual,
31+
});
32+
export const instanceContext: Monad2<URI> & ProductLeft<URI> = {
3333
URI,
34-
...getReaderM(instanceObservable),
35-
asks: f => memo(e => instanceObservable.of(f(e))),
36-
productLeft: (fa, fb) => e => combineLatest(fa(e), fb(e)),
34+
...getReaderM(instanceSink),
35+
productLeft: (fa, fb) => e => sink.sequenceT(fa(e), fb(e)),
3736
};
3837

3938
const sequenceT_ = sequenceT(instanceContext);
@@ -42,7 +41,7 @@ const sequenceArray = array.sequence(instanceContext);
4241
const defer = <E extends object, A, K extends keyof E>(
4342
fa: Context<E, A>,
4443
...keys: K[]
45-
): Context<Omit<E, K>, Context<Pick<E, K>, A>> => pipe(deferReader(fa, ...keys), readerMap(instanceObservable.of));
44+
): Context<Omit<E, K>, Context<Pick<E, K>, A>> => pipe(deferReader(fa, ...keys), readerMap(instanceSink.of));
4645

4746
const combine: ProductMap<URI> = <E, A, R>(...args: NonEmptyArray<Context<E, A> | ProjectMany<A, R>>) => {
4847
const last = args.length - 1;
@@ -51,11 +50,14 @@ const combine: ProductMap<URI> = <E, A, R>(...args: NonEmptyArray<Context<E, A>
5150
return instanceContext.map(fas, as => project(...as));
5251
};
5352

53+
const key = <A>() => <K extends PropertyKey>(key: K): Context<Record<K, A>, A> => e => sink.of(e[key]);
54+
5455
export const context = {
5556
...instanceContext,
5657
...pipeable(instanceContext),
5758
sequenceT: sequenceT_,
5859
sequenceArray,
5960
combine,
6061
defer,
62+
key,
6163
};

packages/rx-utils/src/sink.utils.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@ import { sequenceT } from 'fp-ts/lib/Apply';
44
import { Monoid } from 'fp-ts/lib/Monoid';
55
import { Semigroup } from 'fp-ts/lib/Semigroup';
66

7+
/**
8+
* @deprecated Use `Sink` from `sink2.utils.ts`
9+
*/
710
export const URI = 'Sink';
11+
/**
12+
* @deprecated Use `Sink` from `sink2.utils.ts`
13+
*/
814
export type URI = typeof URI;
915

1016
declare module 'fp-ts/lib/HKT' {
@@ -14,7 +20,7 @@ declare module 'fp-ts/lib/HKT' {
1420
}
1521

1622
/**
17-
* @deprecated Use `MonadObservable` from `@devexperts/utils` to track effects
23+
* @deprecated Use `Sink` from `sink2.utils.ts`
1824
*/
1925
export class Sink<A> {
2026
readonly _A!: A;
@@ -37,14 +43,14 @@ export class Sink<A> {
3743
}
3844

3945
/**
40-
* @deprecated
46+
* @deprecated use `sink.getSemigroup` from `sink2.utils.ts`
4147
*/
4248
export const getSemigroup = <A>(S: Semigroup<A>): Semigroup<Sink<A>> => ({
4349
concat: (x, y) => new Sink(S.concat(x.value, y.value), merge(x.sink$, y.sink$)),
4450
});
4551

4652
/**
47-
* @deprecated
53+
* @deprecated use `sink.getMonoid` from `sink2.utils.ts`
4854
*/
4955
export const getMonoid = <A>(M: Monoid<A>): Monoid<Sink<A>> => ({
5056
...getSemigroup(M),
@@ -57,7 +63,7 @@ const ap = <A, B>(fab: Sink<(a: A) => B>, fa: Sink<A>): Sink<B> => fa.ap(fab);
5763
const chain = <A, B>(fa: Sink<A>, f: (a: A) => Sink<B>): Sink<B> => fa.chain(f);
5864

5965
/**
60-
* @deprecated
66+
* @deprecated Use `instanceSink` from `sink2.utils.ts`
6167
*/
6268
export const sink: Monad1<URI> = {
6369
URI,
@@ -68,6 +74,6 @@ export const sink: Monad1<URI> = {
6874
};
6975

7076
/**
71-
* @deprecated
77+
* @deprecated Use `sink.sequenceT` from `sink2.utils.ts`
7278
*/
7379
export const sequenceTSink = sequenceT(sink);
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { EMPTY, merge, Observable } from 'rxjs';
2+
import { Monad1 } from 'fp-ts/lib/Monad';
3+
import { pipeable } from 'fp-ts/lib/pipeable';
4+
import { sequenceT } from 'fp-ts/lib/Apply';
5+
import { array } from 'fp-ts/lib/Array';
6+
import { Semigroup } from 'fp-ts/lib/Semigroup';
7+
import { Monoid } from 'fp-ts/lib/Monoid';
8+
9+
export interface Sink<A> {
10+
readonly effects: Observable<unknown>;
11+
readonly value: A;
12+
}
13+
export const newSink = <A>(value: A, effects: Observable<unknown>): Sink<A> => ({ value, effects });
14+
15+
export const URI = '@devexperts/rx-utils//Sink';
16+
export type URI = typeof URI;
17+
declare module 'fp-ts/lib/HKT' {
18+
interface URItoKind<A> {
19+
[URI]: Sink<A>;
20+
}
21+
}
22+
23+
export const instanceSink: Monad1<URI> = {
24+
URI,
25+
map: (fa, f) => newSink(f(fa.value), fa.effects),
26+
ap: (fab, fa) => newSink(fab.value(fa.value), merge(fab.effects, fa.effects)),
27+
of: a => newSink(a, EMPTY),
28+
chain: (fa, f) => {
29+
const fb = f(fa.value);
30+
return newSink(fb.value, merge(fa.effects, fb.effects));
31+
},
32+
};
33+
34+
const getSemigroup = <A>(S: Semigroup<A>): Semigroup<Sink<A>> => ({
35+
concat: (x, y) => newSink(S.concat(x.value, y.value), merge(x.effects, y.effects)),
36+
});
37+
38+
const getMonoid = <A>(M: Monoid<A>): Monoid<Sink<A>> => ({
39+
...getSemigroup(M),
40+
empty: instanceSink.of(M.empty),
41+
});
42+
43+
export const sink = {
44+
...instanceSink,
45+
...pipeable(instanceSink),
46+
sequenceT: sequenceT(instanceSink),
47+
sequenceArray: array.sequence(instanceSink),
48+
getSemigroup,
49+
};

0 commit comments

Comments
 (0)