Skip to content

Commit

Permalink
feat: implement a FnClass for combining identifer with implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
TylorS committed Jul 25, 2023
1 parent 51fbe55 commit 7da0d63
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 3 deletions.
21 changes: 21 additions & 0 deletions packages/context/src/fn-class.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as Effect from '@effect/io/Effect'
import { describe, expect, it } from 'vitest'

import { FnClass } from './fn-class.js'

describe(FnClass.name, () => {
it('allows calling a function from Effect context', async () => {
class Add extends FnClass<(x: number, y: number) => Effect.Effect<never, never, number>>() {
static increment = (x: number) => Add.apply(x, 1)
static decrement = (x: number) => Add.apply(x, -1)
}

const test = Add.apply(1, 2).pipe(
Effect.flatMap((x) => Add.increment(x)),
Effect.flatMap((x) => Add.decrement(x)),
Add.provideImplementation((x, y) => Effect.succeed(x + y)),
)

expect(await Effect.runPromise(test)).toBe(3)
})
})
77 changes: 77 additions & 0 deletions packages/context/src/fn-class.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import * as Effect from '@effect/io/Effect'
import * as Layer from '@effect/io/Layer'

import { EffectFn, Fn } from './fn.js'
import { IdentifierOf } from './identifier.js'

export function FnClass<A extends EffectFn<readonly any[]>>() {
return class FnImpl {
readonly __EffectFn__!: A

static get _id() {
return Symbol.for(this.name)
}

get _id() {
return (this.constructor as any)._id
}

static withEffect: <T extends typeof FnImpl, R, E, B>(
this: T,
f: (fn: A) => Effect.Effect<R, E, B>,
) => Effect.Effect<
InstanceType<T> | EffectFn.ResourcesOf<A>,
EffectFn.ErrorsOf<A>,
EffectFn.OutputOf<A>
>

static apply: <T extends typeof FnImpl, Args extends EffectFn.ArgsOf<A>>(
this: T,
...args: Args
) => Effect.Effect<
InstanceType<T> | EffectFn.ResourcesOf<A>,
EffectFn.ErrorsOf<A>,
EffectFn.OutputOf<A>
>

static implement: <T extends typeof FnImpl, F extends EffectFn.Extendable<A>>(
this: T,
f: F,
) => Layer.Layer<EffectFn.ResourcesOf<A>, never, IdentifierOf<T>>

static provideImplementation: {
<T extends typeof FnImpl, F extends EffectFn.Extendable<A>>(
this: T,
f: F,
): <R, E, B>(
effect: Effect.Effect<R, E, B>,
) => Effect.Effect<
Exclude<R, IdentifierOf<T>> | EffectFn.ResourcesOf<A>,
E | EffectFn.ErrorsOf<A>,
B
>

<T extends typeof FnImpl, R, E, B, F extends EffectFn.Extendable<A>>(
this: T,
effect: Effect.Effect<R, E, B>,
f: F,
): Effect.Effect<
Exclude<R, IdentifierOf<T>> | EffectFn.ResourcesOf<A>,
E | EffectFn.ErrorsOf<A>,
B
>
}

static {
/**
* @internal
*/
const _fn: Fn<any, A> = Fn<A>()(this)

this.withEffect = _fn.withEffect as any
this.apply = _fn.apply as any
this.implement = _fn.implement as any
this.provideImplementation = _fn.provideImplementation as any
}
}
}
6 changes: 3 additions & 3 deletions packages/context/src/fn.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import * as Effect from '@effect/io/Effect'
import { describe, expect, it } from 'vitest'

import { Fn } from './fn.js'
import { id } from './identifier.js'

describe(Fn.name, () => {
it('allows calling a function from Effect context', async () => {
class AddService extends id('@typed/context/AddService') {}
const Add = Fn<(x: number, y: number) => Effect.Effect<never, never, number>>()(AddService)
const Add = Fn<(x: number, y: number) => Effect.Effect<never, never, number>>()(
'@typed/context/AddService',
)

const test = Add.apply(1, 2).pipe(Add.provideImplementation((x, y) => Effect.succeed(x + y)))

Expand Down
1 change: 1 addition & 0 deletions packages/context/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './builder.js'
export * from './context.js'
export * from './fn-class.js'
export * from './fn.js'
export * from './identifier.js'
export * from './interfaces.js'
Expand Down

0 comments on commit 7da0d63

Please sign in to comment.