( s: S, max: number, costFn: (s: S, input: In) => Effect.Effect<number, E, R>, decompose: (input: In) => Effect.Effect<Chunk.Chunk<In>, E2, R2>, f: (s: S, input: In) => Effect.Effect<S, E3, R3>, input: Chunk.Chunk<In>, dirty: boolean, cost: number, index: number )
| 1274 | |
| 1275 | /** @internal */ |
| 1276 | const foldWeightedDecomposeEffectFold = <S, In, E, R, E2, R2, E3, R3>( |
| 1277 | s: S, |
| 1278 | max: number, |
| 1279 | costFn: (s: S, input: In) => Effect.Effect<number, E, R>, |
| 1280 | decompose: (input: In) => Effect.Effect<Chunk.Chunk<In>, E2, R2>, |
| 1281 | f: (s: S, input: In) => Effect.Effect<S, E3, R3>, |
| 1282 | input: Chunk.Chunk<In>, |
| 1283 | dirty: boolean, |
| 1284 | cost: number, |
| 1285 | index: number |
| 1286 | ): Effect.Effect<[S, number, boolean, Chunk.Chunk<In>], E | E2 | E3, R | R2 | R3> => { |
| 1287 | if (index === input.length) { |
| 1288 | return Effect.succeed([s, cost, dirty, Chunk.empty<In>()]) |
| 1289 | } |
| 1290 | const elem = pipe(input, Chunk.unsafeGet(index)) |
| 1291 | return pipe( |
| 1292 | costFn(s, elem), |
| 1293 | Effect.map((newCost) => cost + newCost), |
| 1294 | Effect.flatMap((total) => { |
| 1295 | if (total <= max) { |
| 1296 | return pipe( |
| 1297 | f(s, elem), |
| 1298 | Effect.flatMap((s) => |
| 1299 | foldWeightedDecomposeEffectFold(s, max, costFn, decompose, f, input, true, total, index + 1) |
| 1300 | ) |
| 1301 | ) |
| 1302 | } |
| 1303 | return pipe( |
| 1304 | decompose(elem), |
| 1305 | Effect.flatMap((decomposed) => { |
| 1306 | if (decomposed.length <= 1 && !dirty) { |
| 1307 | // If `elem` cannot be decomposed, we need to cross the `max` threshold. To |
| 1308 | // minimize "injury", we only allow this when we haven't added anything else |
| 1309 | // to the aggregate (dirty = false). |
| 1310 | return pipe( |
| 1311 | f(s, elem), |
| 1312 | Effect.map((s) => [s, total, true, pipe(input, Chunk.drop(index + 1))]) |
| 1313 | ) |
| 1314 | } |
| 1315 | if (decomposed.length <= 1 && dirty) { |
| 1316 | // If the state is dirty and `elem` cannot be decomposed, we stop folding |
| 1317 | // and include `elem` in th leftovers. |
| 1318 | return Effect.succeed([s, cost, dirty, pipe(input, Chunk.drop(index))]) |
| 1319 | } |
| 1320 | // `elem` got decomposed, so we will recurse with the decomposed elements pushed |
| 1321 | // into the chunk we're processing and see if we can aggregate further. |
| 1322 | const next = pipe(decomposed, Chunk.appendAll(pipe(input, Chunk.drop(index + 1)))) |
| 1323 | return foldWeightedDecomposeEffectFold(s, max, costFn, decompose, f, next, dirty, cost, 0) |
| 1324 | }) |
| 1325 | ) |
| 1326 | }) |
| 1327 | ) |
| 1328 | } |
| 1329 | |
| 1330 | /** @internal */ |
| 1331 | export const flatMap = dual< |
no test coverage detected
searching dependent graphs…