Skip to content
This repository has been archived by the owner on Feb 13, 2023. It is now read-only.

chore: get rid of Name and refactor #13

Merged
merged 2 commits into from
Oct 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 21 additions & 23 deletions Effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,36 +24,34 @@ export class Effect<
) {
this.id = `${this.kind}(${this.children?.map(U.id.of).join(",") || ""})`;
}

access = <K extends $<keyof T>>(
key: K,
): Effect<T[U.AssertKeyof<T, K>], E, V> => {
return new Effect("Access", (process) => {
return U.memo(() => {
return U.thenOk(
U.all(process.resolve(this), process.resolve(key)),
([target, key]) => target[key],
);
});
}, [this, key]);
};

as = <U extends T>() => {
return this as unknown as Effect<U, E, V>;
};
}

// TODO: make generic?
export type EffectInitRun = (process: Process) => () => unknown;

export abstract class Name<Root extends EffectLike = EffectLike> {
abstract root: Root;

get id(): string {
return this.root.id;
}
}

export type EffectLike<
T = any,
E extends Error = Error,
V extends PropertyKey = PropertyKey,
> = Effect<T, E, V> | Name<EffectLike<T, E, V>>;

export function isEffectLike(inQuestion: unknown): inQuestion is EffectLike {
return inQuestion instanceof Effect || inQuestion instanceof Name;
}

// TODO: fully ensure no promises-wrappers/errors
export type T<U> = U extends EffectLike<infer T> ? T
export type T<U> = U extends Effect<infer T> ? T
: U extends Placeholder<PropertyKey, infer T> ? T
: Exclude<Awaited<U>, Error>;
export type E<U> = U extends EffectLike<any, infer E> ? E : never;
export type V<U> = U extends EffectLike<any, Error, infer V> ? V
export type E<U> = U extends Effect<any, infer E> ? E : never;
export type V<U> = U extends Effect<any, Error, infer V> ? V
: U extends Placeholder ? U["key"]
: never;

export type $<T> = T | EffectLike<T> | Placeholder<PropertyKey, T>;
export type $<T> = T | Effect<T> | Placeholder<PropertyKey, T>;
33 changes: 14 additions & 19 deletions Process.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { EffectLike, isEffectLike, Name } from "./Effect.ts";
import { Effect } from "./Effect.ts";
import { isPlaceholder } from "./Placeholder.ts";

export class Process extends Map<string, () => unknown> {
Expand All @@ -8,35 +8,30 @@ export class Process extends Map<string, () => unknown> {
super();
}

init = (root: EffectLike) => {
const stack: EffectLike[] = [root];
init = (root: Effect) => {
const stack: Effect[] = [root];
while (stack.length) {
const currentSource = stack.pop()!;
if (currentSource instanceof Name) {
stack.push(currentSource.root);
continue;
} else {
let run = this.get(currentSource.id);
if (!run) {
run = currentSource.run(this);
this.set(currentSource.id, run);
currentSource.children?.forEach((arg) => {
if (isEffectLike(arg)) {
stack.push(arg);
}
});
}
let run = this.get(currentSource.id);
if (!run) {
run = currentSource.run(this);
this.set(currentSource.id, run);
currentSource.children?.forEach((arg) => {
if (arg instanceof Effect) {
stack.push(arg);
}
});
}
}
return this.get(root.id)!;
};

run = (effect: EffectLike) => {
run = (effect: Effect) => {
return this.get(effect.id)!;
};

resolve = (x: unknown) => {
return isEffectLike(x)
return x instanceof Effect
? this.run(x)!()
: isPlaceholder(x)
? this.applies[x.key]
Expand Down
4 changes: 2 additions & 2 deletions Runtime.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { E, EffectLike, T, V } from "./Effect.ts";
import { E, Effect, T, V } from "./Effect.ts";
import { UntypedError } from "./Error.ts";
import { EnsureSoleApplies, flattenApplies } from "./Placeholder.ts";
import { Process } from "./Process.ts";
Expand All @@ -17,7 +17,7 @@ export function runtime<Applies extends Record<PropertyKey, unknown>[]>(
}

export interface Runtime<Applies extends PropertyKey> {
<Root extends EffectLike>(
<Root extends Effect>(
root: Root,
...[apply]: [Exclude<V<Root>, Applies>] extends [never] ? []
: [useApplies: UseApplies<V<Root>, Applies>]
Expand Down
30 changes: 0 additions & 30 deletions core/derive.ts

This file was deleted.

20 changes: 0 additions & 20 deletions core/sel.ts

This file was deleted.

File renamed without changes.
22 changes: 22 additions & 0 deletions effects/derive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { E, Effect, T, V } from "../Effect.ts";
import { thrownAsUntypedError } from "../Error.ts";
import * as U from "../util/mod.ts";

export function derive<From, IntoR extends Effect>(
from: From,
into: DeriveInto<From, IntoR>,
): Effect<T<IntoR>, E<From | IntoR>, V<From | IntoR>> {
const e = new Effect("Derive", (process) => {
return (): unknown => {
return U.thenOk(
U.then(process.resolve(from), thrownAsUntypedError(e, into)),
(e) => process.init(e)(),
);
};
}, [from, into]);
return e as any;
}

export type DeriveInto<Target, IntoR extends Effect> = (
resolved: T<Target>,
) => IntoR;
7 changes: 2 additions & 5 deletions core/each.ts → effects/each.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import { $, EffectLike, T } from "../Effect.ts";
import { $, Effect, T } from "../Effect.ts";
import { derive } from "./derive.ts";
import { ls } from "./ls.ts";

export function each<
Elements extends $<unknown[]>,
Into extends EffectLike,
>(
export function each<Elements extends $<unknown[]>, Into extends Effect>(
elements: Elements,
cb: (element: T<Elements>[number]) => Into,
) {
Expand Down
6 changes: 3 additions & 3 deletions core/if.ts → effects/if.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { $, EffectLike } from "../Effect.ts";
import { $, Effect } from "../Effect.ts";
import { derive } from "./derive.ts";

function if_<
Condition extends $<boolean>,
Then extends EffectLike,
Else extends EffectLike,
Then extends Effect,
Else extends Effect,
>(
condition: Condition,
then: Then,
Expand Down
File renamed without changes.
1 change: 0 additions & 1 deletion core/mod.ts → effects/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@ export * from "./if.ts";
export * from "./ls.ts";
export * from "./rc.ts";
export * from "./rec.ts";
export * from "./sel.ts";
export * from "./try.ts";
export * from "./wrap.ts";
File renamed without changes.
File renamed without changes.
11 changes: 5 additions & 6 deletions core/try.ts → effects/try.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { E, Effect, EffectLike, T, V } from "../Effect.ts";
import { E, Effect, T, V } from "../Effect.ts";
import * as U from "../util/mod.ts";

// TODO: fix this
export function try_<
Attempt extends EffectLike,
Attempt extends Effect,
FallbackR extends T<Attempt> | Error,
>(
attempt: Attempt,
Expand All @@ -25,7 +25,6 @@ Object.defineProperty(try_, "name", {
});
export { try_ as try };

export type Catch<
Target extends EffectLike,
CatchR,
> = (attemptError: E<Target>) => CatchR;
export type Catch<Target extends Effect, CatchR> = (
attemptError: E<Target>,
) => CatchR;
File renamed without changes.
2 changes: 1 addition & 1 deletion examples/sel.ts → examples/access.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const x = Z.call(0, () => {
} as const;
});

const y = Z.sel(x, "b");
const y = x.access("b");

const result = Z.runtime()(y);

Expand Down
6 changes: 2 additions & 4 deletions examples/derived.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import { derive } from "../core/derive.ts";
import { derive } from "../effects/derive.ts";
import * as Z from "../mod.ts";

const coinToss = Z.call(0, () => {
return Math.random() > .5;
});

const root = derive(coinToss, (truth) => {
return truth
? Z.call(undefined!, () => "HELLO")
: Z.call(undefined!, () => "GOODBYE");
return Z.call(undefined!, () => truth ? "HELLO" : "GOODBYE");
});

const result = await Z.runtime()(root);
Expand Down
2 changes: 1 addition & 1 deletion mod.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export * from "./core/mod.ts";
export * from "./Effect.ts";
export * from "./effects/mod.ts";
export * from "./Error.ts";
export * from "./Placeholder.ts";
export * from "./Process.ts";
Expand Down
1 change: 1 addition & 0 deletions util/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export type U2I<T> = (T extends any ? (value: T) => any : never) extends
(value: infer R) => any ? R : never;

export type AssertIsO<T> = T extends Record<PropertyKey, unknown> ? T : never;
export type AssertKeyof<T, K> = K extends keyof T ? K : never;

// TODO: delete if unused
export type ValueOf<T> = T[keyof T];
Expand Down
4 changes: 2 additions & 2 deletions util/id.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isEffectLike } from "../Effect.ts";
import { Effect } from "../Effect.ts";
import * as U from "../util/mod.ts";

class IdFactory<T> {
Expand Down Expand Up @@ -32,7 +32,7 @@ export function of(target: unknown): string {
return `fn(${target.name})`;
}
case "object": {
if (isEffectLike(target)) {
if (target instanceof Effect) {
return target.id;
} else if (target === null) {
return "null";
Expand Down