-
-
Notifications
You must be signed in to change notification settings - Fork 507
/
Copy pathChain.ts
163 lines (151 loc) · 5.94 KB
/
Chain.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/**
* The `Chain` type class extends the `Apply` type class with a `chain` operation which composes computations in
* sequence, using the return value of one computation to determine the next computation.
*
* Instances must satisfy the following law in addition to the `Apply` laws:
*
* 1. Associativity: `F.chain(F.chain(fa, afb), bfc) <-> F.chain(fa, a => F.chain(afb(a), bfc))`
*
* Note. `Apply`'s `ap` can be derived: `(fab, fa) => F.chain(fab, f => F.map(fa, f))`
*
* @since 2.0.0
*/
import { Apply, Apply1, Apply2, Apply2C, Apply3, Apply4, Apply3C } from './Apply'
import { HKT, Kind, Kind2, Kind3, Kind4, URIS, URIS2, URIS3, URIS4 } from './HKT'
// -------------------------------------------------------------------------------------
// model
// -------------------------------------------------------------------------------------
/**
* @category type classes
* @since 2.0.0
*/
export interface Chain<F> extends Apply<F> {
readonly chain: <A, B>(fa: HKT<F, A>, f: (a: A) => HKT<F, B>) => HKT<F, B>
}
/**
* @category type classes
* @since 2.0.0
*/
export interface Chain1<F extends URIS> extends Apply1<F> {
readonly chain: <A, B>(fa: Kind<F, A>, f: (a: A) => Kind<F, B>) => Kind<F, B>
}
/**
* @category type classes
* @since 2.0.0
*/
export interface Chain2<F extends URIS2> extends Apply2<F> {
readonly chain: <E, A, B>(fa: Kind2<F, E, A>, f: (a: A) => Kind2<F, E, B>) => Kind2<F, E, B>
}
/**
* @category type classes
* @since 2.0.0
*/
export interface Chain2C<F extends URIS2, E> extends Apply2C<F, E> {
readonly chain: <A, B>(fa: Kind2<F, E, A>, f: (a: A) => Kind2<F, E, B>) => Kind2<F, E, B>
}
/**
* @category type classes
* @since 2.0.0
*/
export interface Chain3<F extends URIS3> extends Apply3<F> {
readonly chain: <R, E, A, B>(fa: Kind3<F, R, E, A>, f: (a: A) => Kind3<F, R, E, B>) => Kind3<F, R, E, B>
}
/**
* @category type classes
* @since 2.2.0
*/
export interface Chain3C<F extends URIS3, E> extends Apply3C<F, E> {
readonly chain: <R, A, B>(fa: Kind3<F, R, E, A>, f: (a: A) => Kind3<F, R, E, B>) => Kind3<F, R, E, B>
}
/**
* @category type classes
* @since 2.0.0
*/
export interface Chain4<F extends URIS4> extends Apply4<F> {
readonly chain: <S, R, E, A, B>(fa: Kind4<F, S, R, E, A>, f: (a: A) => Kind4<F, S, R, E, B>) => Kind4<F, S, R, E, B>
}
// -------------------------------------------------------------------------------------
// combinators
// -------------------------------------------------------------------------------------
/**
* @category combinators
* @since 2.10.0
*/
export function chainFirst<M extends URIS4>(
M: Chain4<M>
): <A, S, R, E, B>(f: (a: A) => Kind4<M, S, R, E, B>) => (first: Kind4<M, S, R, E, A>) => Kind4<M, S, R, E, A>
export function chainFirst<M extends URIS3>(
M: Chain3<M>
): <A, R, E, B>(f: (a: A) => Kind3<M, R, E, B>) => (first: Kind3<M, R, E, A>) => Kind3<M, R, E, A>
export function chainFirst<M extends URIS3, E>(
M: Chain3C<M, E>
): <A, R, B>(f: (a: A) => Kind3<M, R, E, B>) => (first: Kind3<M, R, E, A>) => Kind3<M, R, E, A>
export function chainFirst<M extends URIS2>(
M: Chain2<M>
): <A, E, B>(f: (a: A) => Kind2<M, E, B>) => (first: Kind2<M, E, A>) => Kind2<M, E, A>
export function chainFirst<M extends URIS2, E>(
M: Chain2C<M, E>
): <A, B>(f: (a: A) => Kind2<M, E, B>) => (first: Kind2<M, E, A>) => Kind2<M, E, A>
export function chainFirst<M extends URIS>(
M: Chain1<M>
): <A, B>(f: (a: A) => Kind<M, B>) => (first: Kind<M, A>) => Kind<M, A>
export function chainFirst<M>(M: Chain<M>): <A, B>(f: (a: A) => HKT<M, B>) => (first: HKT<M, A>) => HKT<M, A>
export function chainFirst<M>(M: Chain<M>): <A, B>(f: (a: A) => HKT<M, B>) => (first: HKT<M, A>) => HKT<M, A> {
return (f) => (first) => M.chain(first, (a) => M.map(f(a), () => a))
}
// -------------------------------------------------------------------------------------
// utils
// -------------------------------------------------------------------------------------
/**
* @since 2.10.0
*/
export function bind<M extends URIS4>(
M: Chain4<M>
): <N extends string, A, S, R, E, B>(
name: Exclude<N, keyof A>,
f: (a: A) => Kind4<M, S, R, E, B>
) => (ma: Kind4<M, S, R, E, A>) => Kind4<M, S, R, E, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }>
export function bind<M extends URIS3>(
M: Chain3<M>
): <N extends string, A, R, E, B>(
name: Exclude<N, keyof A>,
f: (a: A) => Kind3<M, R, E, B>
) => (ma: Kind3<M, R, E, A>) => Kind3<M, R, E, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }>
export function bind<M extends URIS3, E>(
M: Chain3C<M, E>
): <N extends string, A, R, B>(
name: Exclude<N, keyof A>,
f: (a: A) => Kind3<M, R, E, B>
) => (ma: Kind3<M, R, E, A>) => Kind3<M, R, E, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }>
export function bind<M extends URIS2>(
M: Chain2<M>
): <N extends string, A, E, B>(
name: Exclude<N, keyof A>,
f: (a: A) => Kind2<M, E, B>
) => (ma: Kind2<M, E, A>) => Kind2<M, E, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }>
export function bind<M extends URIS2, E>(
M: Chain2C<M, E>
): <N extends string, A, B>(
name: Exclude<N, keyof A>,
f: (a: A) => Kind2<M, E, B>
) => (ma: Kind2<M, E, A>) => Kind2<M, E, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }>
export function bind<M extends URIS>(
M: Chain1<M>
): <N extends string, A, B>(
name: Exclude<N, keyof A>,
f: (a: A) => Kind<M, B>
) => (ma: Kind<M, A>) => Kind<M, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }>
export function bind<M>(
M: Chain<M>
): <N extends string, A, B>(
name: Exclude<N, keyof A>,
f: (a: A) => HKT<M, B>
) => (ma: HKT<M, A>) => HKT<M, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }>
export function bind<M>(
M: Chain<M>
): <N extends string, A, B>(
name: Exclude<N, keyof A>,
f: (a: A) => HKT<M, B>
) => (ma: HKT<M, A>) => HKT<M, { readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }> {
return (name, f) => (ma) => M.chain(ma, (a) => M.map(f(a), (b) => Object.assign({}, a, { [name]: b }) as any))
}