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

Commit

Permalink
chore: get rid of Name and refactor (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
harrysolovay authored Oct 28, 2022
1 parent 0ef135c commit f75d610
Show file tree
Hide file tree
Showing 20 changed files with 76 additions and 117 deletions.
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

0 comments on commit f75d610

Please sign in to comment.