Created
April 23, 2025 20:58
-
-
Save titouancreach/c86269f85758da1d882cf9e4eac23a10 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Data, Effect, Pipeable } from "effect"; | |
export const TypeId: unique symbol = Symbol.for("TaggedHandler"); | |
export type TypeId = typeof TypeId; | |
export interface TaggedHandler<T extends { _tag: string }, A, E, R> | |
extends Pipeable.Pipeable { | |
tags: Array<T["_tag"]>; | |
run: (value: T) => Effect.Effect<A, E, R>; | |
readonly [TypeId]: TypeId; | |
} | |
export const make = <T extends { _tag: string }, A, E, R>( | |
tag: T["_tag"], | |
handler: (value: T) => Effect.Effect<A, E, R>, | |
): TaggedHandler<T, A, E, R> => { | |
return { | |
tags: [tag], | |
run: handler, | |
pipe() { | |
// biome-ignore lint/style/noArguments: <explanation> | |
return Pipeable.pipeArguments(this, arguments); | |
}, | |
[TypeId]: TypeId, | |
}; | |
}; | |
export const orElse = < | |
T1 extends { _tag: string }, | |
T2 extends { _tag: string }, | |
A, | |
E, | |
R, | |
A2 = A, | |
E2 = E, | |
R2 = R, | |
>( | |
handler1: TaggedHandler<T1, A, E, R>, | |
handler2: TaggedHandler<T2, A2, E2, R2>, | |
): TaggedHandler<T1 | T2, A | A2, E | E2, R | R2> => { | |
return { | |
tags: [...handler1.tags, ...handler2.tags], | |
run: (value: T1 | T2) => { | |
if (handler1.tags.includes(value._tag)) { | |
return handler1.run(value as T1) as Effect.Effect< | |
A | A2, | |
E | E2, | |
R | R2 | |
>; | |
} | |
return handler2.run(value as T2) as Effect.Effect<A | A2, E | E2, R | R2>; | |
}, | |
[TypeId]: TypeId, | |
pipe() { | |
// biome-ignore lint/style/noArguments: <explanation> | |
return Pipeable.pipeArguments(this, arguments); | |
}, | |
}; | |
}; | |
// Helper pour combiner plusieurs handlers | |
export const combine = <T extends { _tag: string }, A, E, R>( | |
...handlers: Array<TaggedHandler<T, A, E, R>> | |
): TaggedHandler<T, A, E, R> => { | |
return handlers.reduce((acc, handler) => orElse(acc, handler)); | |
}; | |
export const mapEffect = <T extends { _tag: string }, A, E, R, A2>( | |
handler: TaggedHandler<T, A, E, R>, | |
fn: (value: A) => Effect.Effect<A2, E, R>, | |
): TaggedHandler<T, A2, E, R> => { | |
return { | |
tags: handler.tags, | |
run: (value) => handler.run(value).pipe(Effect.flatMap(fn)), | |
[TypeId]: TypeId, | |
pipe() { | |
// biome-ignore lint/style/noArguments: <explanation> | |
return Pipeable.pipeArguments(this, arguments); | |
}, | |
}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment