Play with Managed
Managed represents safe acquisition / usage and release of resources

Managed

1
/**
2
* Lift a pure value into a resource
3
* @param value
4
*/
5
export function pure<R = T.NoEnv, E = T.NoErr, A = unknown>(
6
value: A
7
): Managed<R, E, A>
8
9
/**
10
* Create a Resource by wrapping an IO producing a value that does not need to be disposed
11
*
12
* @param res
13
* @param f
14
*/
15
export function encaseEffect<R, E, A>(
16
rio: T.Effect<R, E, A>
17
): Managed<R, E, A>
18
19
/**
20
* Create a resource from an acquisition and release function
21
* @param acquire
22
* @param release
23
*/
24
export function bracket<R, E, A, R2, E2>(
25
acquire: T.Effect<R, E, A>,
26
release: FunctionN<[A], T.Effect<R2, E2, unknown>>
27
): Managed<R & R2, E | E2, A>
28
29
export function bracketExit<R, E, A, R2, E2>(
30
acquire: T.Effect<R, E, A>,
31
release: FunctionN<[A, Exit<E, unknown>], T.Effect<R2, E2, unknown>>
32
): Managed<R & R2, E | E2, A>
33
34
/**
35
* Lift an IO of a Resource into a resource
36
* @param suspended
37
*/
38
export function suspend<R, E, R2, E2, A>(
39
suspended: T.Effect<R, E, Managed<R2, E2, A>>
40
): Managed<R & R2, E | E2, A>
41
42
/**
43
* Compose dependent resourcess.
44
*
45
* The scope of left will enclose the scope of the resource produced by bind
46
* @param bind
47
*/
48
export function chain<R, E, L, A>(
49
bind: FunctionN<[L], Managed<R, E, A>>
50
): <R2, E2>(ma: Managed<R2, E2, L>) => Managed<R & R2, E | E2, A>
51
52
/**
53
* Map a resource
54
* @param f
55
*/
56
export function map<L, A>(
57
f: FunctionN<[L], A>
58
): <R, E>(res: Managed<R, E, L>) => Managed<R, E, A>
59
60
/**
61
* Zip two resources together with the given function.
62
*
63
* The scope of resa will enclose the scope of resb
64
* @param resa
65
* @param resb
66
* @param f
67
*/
68
export function zipWith<R, E, A, R2, E2, B, C>(
69
resa: Managed<R, E, A>,
70
resb: Managed<R2, E2, B>,
71
f: FunctionN<[A, B], C>
72
): Managed<R & R2, E | E2, C>
73
74
/**
75
* Zip two resources together as a tuple.
76
*
77
* The scope of resa will enclose the scope of resb
78
* @param resa
79
* @param resb
80
*/
81
export function zip<R, E, A, R2, E2, B>(
82
resa: Managed<R, E, A>,
83
resb: Managed<R2, E2, B>
84
): Managed<R & R2, E | E2, readonly [A, B]>
85
86
/**
87
* Apply the function produced by resfab to the value produced by resa to produce a new resource.
88
* @param resa
89
* @param resfab
90
*/
91
export function ap<R, E, A, R2, E2, B>(
92
resa: Managed<R, E, A>,
93
resfab: Managed<R2, E2, FunctionN<[A], B>>
94
): Managed<R & R2, E | E2, B>
95
96
/**
97
* Flipped version of ap
98
* @param resfab
99
* @param resa
100
*/
101
function ap_<R, E, A, B, R2, E2>(
102
resfab: Managed<R, E, FunctionN<[A], B>>,
103
resa: Managed<R2, E2, A>
104
): Managed<R & R2, E | E2, B>
105
106
/**
107
* Map a resource to a static value
108
*
109
* This creates a resource of the provided constant b where the produced A has the same lifetime internally
110
* @param fa
111
* @param b
112
*/
113
export function as<R, E, A, B>(fa: Managed<R, E, A>, b: B): Managed<R, E, B>
114
115
/**
116
* Curried form of as
117
* @param b
118
*/
119
export function to<B>(
120
b: B
121
): <R, E, A>(fa: Managed<R, E, A>) => Managed<R, E, B>
122
123
/**
124
* Construct a new 'hidden' resource using the produced A with a nested lifetime
125
* Useful for performing initialization and cleanup that clients don't need to see
126
* @param left
127
* @param bind
128
*/
129
export function chainTap<R, E, A, R2, E2>(
130
left: Managed<R, E, A>,
131
bind: FunctionN<[A], Managed<R2, E2, unknown>>
132
): Managed<R & R2, E | E2, A>
133
134
/**
135
* Curried form of chainTap
136
* @param bind
137
*/
138
export function chainTapWith<R, E, A>(
139
bind: FunctionN<[A], Managed<R, E, unknown>>
140
): FunctionN<[Managed<R, E, A>], Managed<R, E, A>>
141
142
/**
143
* Curried data last form of use
144
* @param f
145
*/
146
export function consume<R, E, A, B>(
147
f: FunctionN<[A], T.Effect<R, E, B>>
148
): <R2, E2>(ma: Managed<R2, E2, A>) => T.Effect<R & R2, E | E2, B>
149
150
/**
151
* Create a Resource from the fiber of an IO.
152
* The acquisition of this resource corresponds to forking rio into a fiber.
153
* The destruction of the resource is interrupting said fiber.
154
* @param rio
155
*/
156
export function fiber<R, E, A>(
157
rio: T.Effect<R, E, A>
158
): Managed<R, never, T.Fiber<E, A>>
159
160
/**
161
* Use a resource to produce a program that can be run.s
162
* @param res
163
* @param f
164
*/
165
export function use<R, E, A, R2, E2, B>(
166
res: Managed<R, E, A>,
167
f: FunctionN<[A], T.Effect<R2, E2, B>>
168
): T.Effect<R & R2, E | E2, B>
169
170
export interface Leak<R, E, A> {
171
a: A;
172
release: T.Effect<R, E, unknown>;
173
}
174
175
/**
176
* Create an IO action that will produce the resource for this managed along with its finalizer
177
* action seperately.
178
*
179
* If an error occurs during allocation then any allocated resources should be cleaned up, but once the
180
* Leak object is produced it is the callers responsibility to ensure release is invoked.
181
* @param res
182
*/
183
export function allocate<R, E, A>(
184
res: Managed<R, E, A>
185
): T.Effect<R, E, Leak<R, E, A>>
186
187
/**
188
* Use a resource to provide the environment to a WaveR
189
* @param man
190
* @param ma
191
*/
192
export function provideTo<R extends T.Env, E, R2 extends T.Env, A, E2>(
193
man: Managed<R, E, R2>,
194
ma: T.Effect<R2, E2, A>
195
): T.Effect<R, E | E2, A>
196
197
// Instances
198
export const managed: Monad3E<URI> = {
199
URI,
200
of: pure,
201
map: map_,
202
ap: ap_,
203
chain: chain_
204
} as const;
205
206
// semigroup for result combination
207
export function getSemigroup<R, E, A>(
208
Semigroup: Semigroup<A>
209
): Semigroup<Managed<R, E, A>>
210
211
// get monoid to compose result
212
export function getMonoid<R, E, A>(
213
Monoid: Monoid<A>
214
): Monoid<Managed<R, E, A>>
215
216
// provide environment
217
export function provideAll<R>(
218
r: R
219
): <E, A>(ma: Managed<R, E, A>) => Managed<T.NoEnv, E, A>
Copied!

Usage

1
import { effect as T, managed as M } from "@matechs/effect";
2
import { Do } from "fp-ts-contrib/lib/Do";
3
4
const db: { kv: Record<string, string> } = { kv: {} }; // simulate a resource
5
6
const database = M.bracket(T.pure(db), ref =>
7
T.sync(() => {
8
ref.kv = {}; // cleanup resource on release
9
})
10
);
11
12
const program = M.use(database, ref => // use the resource
13
Do(T.effect)
14
.do(
15
T.sync(() => {
16
ref.kv["foo"] = "bar"; // write data
17
})
18
)
19
.do(
20
T.sync(() => {
21
ref.kv["bar"] = "gin"; // write data
22
})
23
)
24
.do(T.raiseError("error!")) // raise an error
25
.return(() => {})
26
);
27
28
T.run(program, () => {
29
console.log(db); // logs => { kv: {} } (release invoked)
30
});
Copied!
Note that Managed can represent any resource, for example database connections and anything that need safe cleanup. Additionally, finalizers (like release in this case) are guaranteed to run even if effect is interrupted while the resource is in usage.
Last modified 1yr ago
Copy link
Contents
Managed
Usage