Play with Effect
Core functions available to create and transform effects

Module

1
// pure value
2
export function pure<A>(a: A): Effect<NoEnv, NoErr, A>
3
4
// create an errored effect
5
export function raised<E, A = never>(e: Cause<E>): Effect<NoEnv, E, A>
6
7
// raise an error (like "throw")
8
export function raiseError<E, A = never>(e: E): Effect<NoEnv, E, A>
9
10
// raise an abort reason (unknown error)
11
export function raiseAbort(u: unknown): Effect<NoEnv, NoErr, never>
12
13
// raise an interruption signal in the execution fiber
14
export const raiseInterrupt: Effect<NoEnv, NoErr, never>
15
16
// create a completed effect with the same exit as the one provided
17
export function completed<E, A>(exit: Exit<E, A>): Effect<NoEnv, E, A>
18
19
// suspend execution of the thunk (give space for interrupt)
20
export function suspended<R, E, A>(
21
thunk: Lazy<Effect<R, E, A>>
22
): Effect<R, E, A>
23
24
// encase a sync computation
25
export function sync<E = NoErr, A = unknown>(
26
thunk: Lazy<A>
27
): Effect<NoEnv, E, A>
28
29
// try a sync computation
30
export function trySync<E = unknown, A = unknown>(
31
thunk: Lazy<A>
32
): Effect<NoEnv, E, A>
33
34
// try a sync computation mapping the catched exception
35
export function trySyncMap<E = unknown>(
36
onError: (e: unknown) => E
37
): <A = unknown>(thunk: Lazy<A>) => Effect<NoEnv, E, A>
38
39
// wrap an async callback into an effect, op return Lazy is triggered
40
// on cancel
41
// type AsyncContFn<E, A> = F.FunctionN<[Ei.Either<E, A>], void>;
42
// type AsyncCancelContFn = F.FunctionN<[(error?: Error) => void], void>;
43
// type AsyncFn<E, A> = F.FunctionN<[AsyncContFn<E, A>], AsyncCancelContFn>;
44
export function async<E, A>(op: AsyncFn<E, A>): Effect<NoEnv, E, A>
45
46
// wrap an async callback into an effect that cannot fail
47
export function asyncTotal<A>(
48
op: FunctionN<[FunctionN<[A], void>], Lazy<void>>
49
): Effect<NoEnv, NoErr, A>
50
51
// denote a region (interruptible or not)
52
export function interruptibleRegion<R, E, A>(
53
inner: Effect<R, E, A>,
54
flag: boolean
55
): Effect<R, E, A>
56
57
// encase an either into an effect
58
export function encaseEither<E, A>(e: Either<E, A>): Effect<NoEnv, E, A>
59
60
// encase an option into an effect
61
export function encaseOption<E, A>(
62
o: Option<A>,
63
onError: Lazy<E>
64
): Effect<NoEnv, E, A>
65
66
// encase nullable pure value
67
export function fromNullableM<R, E, A>(
68
ma: Effect<R, E, A>
69
): Effect<R, E, Option<A>>
70
71
// encase promise
72
export function fromPromise<A>(
73
thunk: Lazy<Promise<A>>
74
): Effect<NoEnv, unknown, A>
75
76
// encase promise mapping error
77
export function fromPromiseMap<E>(
78
onError: (e: unknown) => E
79
): <A>(thunk: Lazy<Promise<A>>) => Effect<NoEnv, E, A>
80
81
// fold an effect handling success and failure
82
export function foldExit<E1, RF, E2, A1, E3, A2, RS>(
83
failure: FunctionN<[Cause<E1>], Effect<RF, E2, A2>>,
84
success: FunctionN<[A1], Effect<RS, E3, A2>>
85
): <R>(io: Effect<R, E1, A1>) => Effect<RF & RS & R, E2 | E3, A2>
86
87
// list a function into an effect
88
export function lift<A, B>(
89
f: FunctionN<[A], B>
90
): <R, E>(io: Effect<R, E, A>) => Effect<R, E, B>
91
92
// map to constant
93
export function as<R, E, A, B>(io: Effect<R, E, A>, b: B): Effect<R, E, B>
94
95
export function to<B>(b: B): <R, E, A>(io: Effect<R, E, A>) => Effect<R, E, B>
96
97
// chain without changing outout
98
export function chainTap<R, E, A>(
99
bind: FunctionN<[A], Effect<R, E, unknown>>
100
): <R2, E2>(inner: Effect<R2, E2, A>) => Effect<R & R2, E | E2, A>
101
102
// as unit
103
export function asUnit<R, E, A>(io: Effect<R, E, A>): Effect<R, E, void>
104
105
// unit
106
export const unit: Effect<NoEnv, NoErr, void>
107
108
// handle raised error
109
export function chainError<R, E1, E2, A>(
110
f: FunctionN<[E1], Effect<R, E2, A>>
111
): <R2>(rio: Effect<R2, E1, A>) => Effect<R & R2, E2, A>
112
113
// map raised error
114
export function mapError<E1, E2>(
115
f: FunctionN<[E1], E2>
116
): <R, A>(io: Effect<R, E1, A>) => Effect<R, E2, A>
117
118
// zip two effects with a function
119
export function zipWith<R, E, A, R2, E2, B, C>(
120
first: Effect<R, E, A>,
121
second: Effect<R2, E2, B>,
122
f: FunctionN<[A, B], C>
123
): Effect<R & R2, E | E2, C>
124
125
// zip with identity
126
export function zip<R, E, A, R2, E2, B>(
127
first: Effect<R, E, A>,
128
second: Effect<R2, E2, B>
129
): Effect<R & R2, E | E2, readonly [A, B]>
130
131
// zip with first
132
export function applyFirst<R, E, A, R2, E2, B>(
133
first: Effect<R, E, A>,
134
second: Effect<R2, E2, B>
135
): Effect<R & R2, E | E2, A>
136
137
// zip with second
138
export function applySecond<R, E, A, R2, E2, B>(
139
first: Effect<R, E, A>,
140
second: Effect<R2, E2, B>
141
): Effect<R & R2, E | E2, B>
142
143
// zip with second lazy
144
export function applySecondL<R, E, A, R2, E2, B>(
145
first: Effect<R, E, A>,
146
second: Lazy<Effect<R2, E2, B>>
147
): Effect<R & R2, E | E2, B>
148
149
// flipped apply
150
export function ap__<R, E, A, R2, E2, B>(
151
ioa: Effect<R, E, A>,
152
iof: Effect<R2, E2, FunctionN<[A], B>>
153
): Effect<R & R2, E | E2, B>
154
155
// parallel zip equivalents
156
export function parZipWith<R, R2, E, E2, A, B, C>(
157
ioa: Effect<R, E, A>,
158
iob: Effect<R2, E2, B>,
159
f: FunctionN<[A, B], C>
160
): Effect<R & R2, E | E2, C>
161
162
export function parZip<R, R2, E, A, B>(
163
ioa: Effect<R, E, A>,
164
iob: Effect<R2, E, B>
165
): Effect<R & R2, E, readonly [A, B]>
166
167
export function parApplyFirst<R, R2, E, A, B>(
168
ioa: Effect<R, E, A>,
169
iob: Effect<R2, E, B>
170
): Effect<R & R2, E, A>
171
172
export function parApplySecond<R, R2, E, A, B>(
173
ioa: Effect<R, E, A>,
174
iob: Effect<R2, E, B>
175
): Effect<R & R2, E, B>
176
177
export function parAp<R, R2, E, A, B>(
178
ioa: Effect<R, E, A>,
179
iof: Effect<R2, E, FunctionN<[A], B>>
180
): Effect<R & R2, E, B>
181
182
export function parAp_<R, R2, E, E2, A, B>(
183
iof: Effect<R, E, FunctionN<[A], B>>,
184
ioa: Effect<R2, E2, A>
185
): Effect<R & R2, E | E2, B>
186
187
// flip A and E
188
export function flip<R, E, A>(io: Effect<R, E, A>): Effect<R, A, E>
189
190
// execute forever or until failure
191
export function forever<R, E, A>(io: Effect<R, E, A>): Effect<R, E, A>
192
193
// get the result of executing io
194
export function result<R, E, A>(
195
io: Effect<R, E, A>
196
): Effect<R, NoErr, Exit<E, A>>
197
198
// make io interruptible
199
export function interruptible<R, E, A>(io: Effect<R, E, A>): Effect<R, E, A>
200
201
// make io non interruptible
202
export function uninterruptible<R, E, A>(io: Effect<R, E, A>): Effect<R, E, A>
203
204
// bracket with full exit control
205
export function bracketExit<R, E, A, B, R2, E2, R3, E3>(
206
acquire: Effect<R, E, A>,
207
release: FunctionN<[A, Exit<E | E3, B>], Effect<R2, E2, unknown>>,
208
use: FunctionN<[A], Effect<R3, E3, B>>
209
): Effect<R & R2 & R3, E | E2 | E3, B>
210
211
// bracket not dealing with use result
212
export function bracket<R, E, A, R2, E2, R3, E3, B>(
213
acquire: Effect<R, E, A>,
214
release: FunctionN<[A], Effect<R2, E2, unknown>>,
215
use: FunctionN<[A], Effect<R3, E3, B>>
216
): Effect<R & R2 & R3, E | E2 | E3, B>
217
218
// run finalizer on complete
219
export function onComplete<R, E, A, R2, E2>(
220
ioa: Effect<R, E, A>,
221
finalizer: Effect<R2, E2, unknown>
222
): Effect<R & R2, E | E2, A>
Copied!
1
// run finalizer on interrupt
2
export function onInterrupted<R, E, A, R2, E2>(
3
ioa: Effect<R, E, A>,
4
finalizer: Effect<R2, E2, unknown>
5
): Effect<R & R2, E | E2, A>
6
7
// introduce a gap to allow other fibers to execute
8
export const shifted: Effect<NoEnv, NoErr, void>
9
10
// add shift before io
11
export function shiftBefore<E, A>(
12
io: Effect<NoEnv, E, A>
13
): Effect<NoEnv, E, A>
14
15
// add shift after io
16
export function shiftAfter<E, A>(io: Effect<NoEnv, E, A>): Effect<NoEnv, E, A>
17
18
// shift and return control to js thread
19
export const shiftedAsync: Effect<NoEnv, NoErr, void>
20
21
export function shiftAsyncBefore<R, E, A>(
22
io: Effect<R, E, A>
23
): Effect<R, E, A>
24
25
export function shiftAsyncAfter<R, E, A>(io: Effect<R, E, A>): Effect<R, E, A>
26
27
// never return
28
export const never: Effect<NoEnv, NoErr, never>
29
30
// add delay to effect
31
export function delay<R, E, A>(
32
inner: Effect<R, E, A>,
33
ms: number
34
): Effect<R, E, A>
35
36
export function liftDelay(
37
ms: number
38
): <R, E, A>(io: Effect<R, E, A>) => Effect<R, E, A>
39
40
// fork into new fiber
41
export function fork<R, E, A>(
42
io: Effect<R, E, A>,
43
name?: string
44
): Effect<R, NoErr, Fiber<E, A>>
45
46
// race and fold
47
export function raceFold<R, R2, R3, R4, E1, E2, E3, A, B, C>(
48
first: Effect<R, E1, A>,
49
second: Effect<R2, E2, B>,
50
onFirstWon: FunctionN<[Exit<E1, A>, Fiber<E2, B>], Effect<R3, E3, C>>,
51
onSecondWon: FunctionN<[Exit<E2, B>, Fiber<E1, A>], Effect<R4, E3, C>>
52
): Effect<R & R2 & R3 & R4, E3, C>
53
54
// race with timeout
55
export function timeoutFold<R, E1, E2, A, B>(
56
source: Effect<R, E1, A>,
57
ms: number,
58
onTimeout: FunctionN<[Fiber<E1, A>], Effect<NoEnv, E2, B>>,
59
onCompleted: FunctionN<[Exit<E1, A>], Effect<NoEnv, E2, B>>
60
): Effect<R, E2, B>
61
62
// race and get first (that completes or error)
63
export function raceFirst<R, R2, E, A>(
64
io1: Effect<R, E, A>,
65
io2: Effect<R2, E, A>
66
): Effect<R & R2, E, A>
67
68
// race and get first success
69
export function race<R, R2, E, A>(
70
io1: Effect<R, E, A>,
71
io2: Effect<R2, E, A>
72
): Effect<R & R2, E, A>
73
74
// convert error to abort
75
export function orAbort<R, E, A>(io: Effect<R, E, A>): Effect<R, NoErr, A>
76
77
// timeout returning option of result
78
export function timeoutOption<R, E, A>(
79
source: Effect<R, E, A>,
80
ms: number
81
): Effect<R, E, Option<A>>
Copied!
1
// run effect calling callback on completion
2
export function run<E, A>(
3
io: Effect<{}, E, A>,
4
callback?: FunctionN<[Exit<E, A>], void>
5
): Lazy<void>
6
7
// run effect as failable promise
8
export function runToPromise<E, A>(io: Effect<{}, E, A>): Promise<A>
9
10
// run effect as non failable promise of exit result
11
export function runToPromiseExit<E, A>(
12
io: Effect<{}, E, A>
13
): Promise<Exit<E, A>>
14
15
// alternatively run fy if fx fails
16
export function alt<R2, E2, A>(
17
fy: () => Effect<R2, E2, A>
18
): <R, E>(fx: Effect<R, E, A>) => Effect<R & R2, E | E2, A>
19
20
// instances
21
export const effect: EffectMonad = {
22
URI,
23
map: map_,
24
of: pure,
25
ap: ap_,
26
chain: chain_,
27
bimap: bimap_,
28
mapLeft: mapLeft_,
29
mapError: mapLeft_,
30
throwError: raiseError,
31
chainError: chainError_,
32
foldExit: foldExit_,
33
chainTap: chainTap_,
34
alt: alt_
35
};
36
37
export const parEffect: Monad3E<URI> & Bifunctor3<URI> & MonadThrow3E<URI> = {
38
URI,
39
map: map_,
40
of: pure,
41
ap: parAp_,
42
chain: chain_,
43
bimap: bimap_,
44
mapLeft: mapLeft_,
45
throwError: raiseError
46
};
47
48
// pipeable combinators
49
const {
50
ap,
51
apFirst,
52
apSecond,
53
bimap,
54
chain,
55
chainFirst,
56
filterOrElse,
57
flatten,
58
fromEither,
59
fromOption,
60
fromPredicate,
61
map,
62
mapLeft
63
} = pipeable(effect);
64
65
// get a semigroup to combine results
66
export function getSemigroup<R, E, A>(
67
s: Semigroup<A>
68
): Semigroup<Effect<R, E, A>>
69
70
// get a monoid for result
71
export function getMonoid<R, E, A>(m: Monoid<A>): Monoid<Effect<R, E, A>>
72
73
/* conditionals */
74
export function when(
75
predicate: boolean
76
): <R, E, A>(ma: Effect<R, E, A>) => Effect<R, E, Op.Option<A>>
77
78
export function or_(
79
predicate: boolean
80
): <R, E, A>(
81
ma: Effect<R, E, A>
82
) => <R2, E2, B>(
83
mb: Effect<R2, E2, B>
84
) => Effect<R & R2, E | E2, Ei.Either<A, B>>
85
86
export function or<R, E, A>(
87
ma: Effect<R, E, A>
88
): <R2, E2, B>(
89
mb: Effect<R2, E2, B>
90
) => (predicate: boolean) => Effect<R & R2, E | E2, Ei.Either<A, B>>
91
92
export function or<R, E, A>(
93
ma: Effect<R, E, A>
94
): <R2, E2, B>(
95
mb: Effect<R2, E2, B>
96
) => (predicate: boolean) => Effect<R & R2, E | E2, Ei.Either<A, B>>
97
98
export function cond<R, E, A>(
99
ma: Effect<R, E, A>
100
): <R2, E2, B>(
101
mb: Effect<R2, E2, B>
102
) => (predicate: boolean) => Effect<R & R2, E | E2, A | B>
103
104
// parallel sequence
105
export function sequenceP(
106
n: number
107
): <R, E, A>(ops: Array<Effect<R, E, A>>) => Effect<R, E, Array<A>>
108
109
// given semigroup for raised error get a semigroup of cause
110
export function getCauseSemigroup<E>(S: Semigroup<E>): Semigroup<Cause<E>>
111
112
// get validation monad given semigroup of error
113
export function getValidationM<E>(S: Semigroup<E>)
114
115
// get validation monad given semigroup of couse
116
export function getCauseValidationM<E>(
117
S: Semigroup<Cause<E>>
118
): Monad3EC<URI, E> & MonadThrow3EC<URI, E> & Alt3EC<URI, E>
119
120
// wrap node standard (inspired by fp-ts taskify)
121
export function effectify<L, R>(
122
f: (cb: (e: L | null | undefined, r?: R) => void) => void
123
): () => Effect<NoEnv, L, R>;
124
export function effectify<A, L, R>(
125
f: (a: A, cb: (e: L | null | undefined, r?: R) => void) => void
126
): (a: A) => Effect<NoEnv, L, R>;
127
export function effectify<A, B, L, R>(
128
f: (a: A, b: B, cb: (e: L | null | undefined, r?: R) => void) => void
129
): (a: A, b: B) => Effect<NoEnv, L, R>;
130
export function effectify<A, B, C, L, R>(
131
f: (a: A, b: B, c: C, cb: (e: L | null | undefined, r?: R) => void) => void
132
): (a: A, b: B, c: C) => Effect<NoEnv, L, R>;
133
export function effectify<A, B, C, D, L, R>(
134
f: (
135
a: A,
136
b: B,
137
c: C,
138
d: D,
139
cb: (e: L | null | undefined, r?: R) => void
140
) => void
141
): (a: A, b: B, c: C, d: D) => Effect<NoEnv, L, R>;
142
export function effectify<A, B, C, D, E, L, R>(
143
f: (
144
a: A,
145
b: B,
146
c: C,
147
d: D,
148
e: E,
149
cb: (e: L | null | undefined, r?: R) => void
150
) => void
151
): (a: A, b: B, c: C, d: D, e: E) => Effect<NoEnv, L, R>;
152
export function effectify<L, R>(f: Function): () => Effect<NoEnv, L, R>
Copied!

Usage

Basic usage, detailed examples will be presented in the following sections
1
import { effect as T, exit as E } from "@matechs/effect";
2
import { right } from "fp-ts/lib/Either";
3
import { semigroupSum, fold } from "fp-ts/lib/Semigroup";
4
5
const pureValues = T.pure(1);
6
7
const syncValues = T.sync(() => 1);
8
9
const syncTry = T.trySync<Error>(() => {
10
// tslint:disable-next-line: no-string-throw
11
throw "error";
12
});
13
14
const asyncValue = T.async<never, number>(r => {
15
const timer = setTimeout(() => {
16
r(right(10));
17
}, 100);
18
19
return (cb) => {
20
clearTimeout(timer);
21
cb()
22
};
23
});
24
25
const sumOf = fold(T.getSemigroup(semigroupSum))(T.pure(0), [
26
pureValues,
27
syncValues,
28
asyncValue
29
]);
30
31
const foldExit = E.fold(
32
a => console.log(a),
33
e => console.error("error:", e),
34
e => console.error("abort", e),
35
() => console.error("interrupt")
36
);
37
38
T.run(pureValues, foldExit); // print 1
39
T.run(syncValues, foldExit); // print 1
40
T.run(syncTry, foldExit); // print error: error
41
T.run(asyncValue, foldExit); // print 10
42
T.run(sumOf, foldExit); // print 12
Copied!
Last modified 1yr ago
Copy link
Contents
Module
Usage