Skip to content

Commit

Permalink
figuring out a recursion API
Browse files Browse the repository at this point in the history
  • Loading branch information
mccraigmccraig committed Nov 16, 2023
1 parent 4e98b27 commit 75c57bb
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 8 deletions.
53 changes: 49 additions & 4 deletions src/object_chain.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Effect } from "effect"
import { Tagged, Tag } from "./tagged.ts"
import { Effect, Context } from "effect"
import { FxFn } from "./fx_fn.ts"
import { Tagged, Tag, tagStr } from "./tagged.ts"
import { UnionFromTuple, ChainObjectSteps } from "./object_builders.ts"
import { UPObjectStepSpec, ObjectStepsDepsU, ObjectStepsErrorsU, ChainObjectStepsReturn, chainObjectStepsProg } from "./object_builders.ts"

Expand Down Expand Up @@ -40,7 +41,7 @@ export function objectChain<Input extends Tagged>() {

return {
tag: tag,
tagStr: tag.tag,
tagStr: tagStr(tag),
steps: steps,
program: chainObjectStepsProg<Input>()(steps)
} as ObjectChain<Input, Steps>
Expand All @@ -59,4 +60,48 @@ export function addSteps<Input extends Tagged,

// deno-lint-ignore no-explicit-any
return objectChain<Input>()(chain.tag, newSteps as any) as ObjectChain<Input, readonly [...Steps, ...AdditionalSteps]>
}
}

// a type for a service which can run an ObjectChain
export type ObjectChainService<Input extends Tagged, R, E, V extends Tagged> = {
readonly buildObject: (i: Input) => Effect.Effect<R, E, V>
}

export type ObjectChainServiceTag<Input extends Tagged, R, E, V extends Tagged> =
Context.Tag<Tag<Input>, ObjectChainService<Input, R, E, V>>

export type RunObjectChainFxFn<Input extends Tagged, R, E, V extends Tagged> = FxFn<Input, R, E, V>

// make an ObjectChainService impl with given Id which will run an ObjectChain for a particular Input
// ooo - maybe the Context.Tag Id type should also be the Tagged type - would be a nice symmetry
// and avoid boilerplate
export function makeObjectChainServiceImpl
<Input extends Tagged,
Steps extends readonly [...UPObjectStepSpec[]],
Chain extends ObjectChain<Input, Steps>,
R, E, V extends Tagged>
(_contextTag: ObjectChainServiceTag<Input, R, E, V>,
_chain: Chain) {
return undefined as unknown as ObjectChainService<Input, R, E, V>
}

// provide an implementation of the ObjectChainService for this chain
// to an Effect
export function provideObjectChainServiceImpl
<Input extends Tagged,
Steps extends readonly [...UPObjectStepSpec[]],
Chain extends ObjectChain<Input, Steps>,
R, E, V extends Tagged>
(effect: Effect.Effect<any, any, any>,
contextTag: ObjectChainServiceTag<Input, R, E, V>,
chain: Chain) {

return Effect.provideService(effect, contextTag, makeObjectChainServiceImpl(contextTag, chain as any))
}


export function runObjectChainFxFn
<ContextTag extends ObjectChainServiceTag<Input, R, E, V>, Input extends Tagged, R, E, V extends Tagged>
(_tag: ContextTag) {
return undefined as unknown as Effect.Effect<R, E, V>
}
4 changes: 4 additions & 0 deletions src/object_chain_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,8 @@ Deno.test("addSteps lets you add steps", () => {
formatPushNotification: "Welcome Bar of Foo",
sendPush: "push sent OK: Welcome Bar of Foo"
})
})

Deno.test("recursion with RunObjectChainFxFn", () => {

})
25 changes: 21 additions & 4 deletions src/tagged.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
export interface Tagged { readonly tag: string }
export type Tag<T extends Tagged> = { readonly tag: T['tag'] }

// build a tag value for an Tagged type,
export interface Tagged {
readonly tag: string
}

const tagKey: unique symbol = Symbol()

export type Tag<T extends Tagged> = {
readonly [tagKey]: T['tag']
}

// build a tag value for a Tagged type,
// forcing the tag param to match the Tagged.tag string
// const aTag = tag<ATagged>("ATagged")
export const tag = <T extends Tagged>(tag: T['tag']): Tag<T> => { return { tag } }
export const tag = <T extends Tagged>(tag: T['tag']): Tag<T> => {
return {
[tagKey]: tag
}
}

// get the tag string from a Tag
export const tagStr = <T extends Tagged>(tag: Tag<T>): Tag<T>[typeof tagKey] => {
return tag[tagKey]
}

0 comments on commit 75c57bb

Please sign in to comment.