From fc217da6c57a90313e2a80fe60668af197dae599 Mon Sep 17 00:00:00 2001 From: gvergnaud Date: Sun, 16 Jul 2023 01:22:37 +0200 Subject: [PATCH] try new core idea --- src/internals/core/Core.ts | 8 +- src/internals/core/Core2.ts | 138 +++++++++++++++++++++++++++ src/internals/core/impl/MergeArgs.ts | 9 ++ 3 files changed, 151 insertions(+), 4 deletions(-) create mode 100644 src/internals/core/Core2.ts diff --git a/src/internals/core/Core.ts b/src/internals/core/Core.ts index 4f9f630..0f8095a 100644 --- a/src/internals/core/Core.ts +++ b/src/internals/core/Core.ts @@ -1,8 +1,8 @@ import { ExcludePlaceholders, MergeArgs } from "./impl/MergeArgs"; import { Head } from "../helpers"; -declare const rawArgs: unique symbol; -type rawArgs = typeof rawArgs; +export declare const rawArgs: unique symbol; +export type rawArgs = typeof rawArgs; /** * Base interface for all functions. @@ -36,8 +36,8 @@ export interface Fn { return: unknown; } -declare const unset: unique symbol; -declare const _: unique symbol; +export declare const unset: unique symbol; +export declare const _: unique symbol; /** * A placeholder type that can be used to indicate that a parameter is not set. diff --git a/src/internals/core/Core2.ts b/src/internals/core/Core2.ts new file mode 100644 index 0000000..d2e943f --- /dev/null +++ b/src/internals/core/Core2.ts @@ -0,0 +1,138 @@ +import { _, unset } from "./Core"; +import { ExcludePlaceholders, ExcludeUnset, MergeArgs } from "./impl/MergeArgs"; +import * as NumberImpl from "../numbers/impl/numbers"; + +/** + * Core + */ + +export interface Fn { + inputTypes: input; + args: unknown; + return: unknown; +} + +interface Ap extends Fn { + name: "Ap"; + + inputTypes: fn["inputTypes"]; + + argsArray: Extract; + allArgs: [...partialArgs, ...this["argsArray"]]; + + expectedArgsCount: fn["inputTypes"]["length"]; + providedArgsCount: ExcludePlaceholders["length"]; + + return: NumberImpl.Compare< + this["providedArgsCount"], + this["expectedArgsCount"] + > extends 1 | 0 + ? Apply> + : Ap; +} + +export type Apply = (fn & { + args: args; +})["return"]; + +export type $< + fn extends Fn, + arg0 extends fn["inputTypes"][0] | _ | unset = unset, + arg1 extends fn["inputTypes"][1] | _ | unset = unset, + arg2 extends fn["inputTypes"][2] | _ | unset = unset, + arg3 extends fn["inputTypes"][3] | _ | unset = unset +> = ((fn extends { name: "Ap" } ? fn : Ap) & { + args: ExcludeUnset<[arg0, arg1, arg2, arg3]>; +})["return"]; + +type Args = Extract; +type Arg0 = Extract[0]; +type Arg1 = Extract[1]; +type Arg2 = Extract[2]; +type Arg3 = Extract[3]; + +type ExpectNumber = [a]; +// arguments are typed internally: +interface TypedArgsTest extends Fn<[number, string]> { + works: ExpectNumber>; // ✅ + fails: ExpectNumber>; + // ~~~~~~~~~~ ❌ + return: true; +} + +interface Div extends Fn<[number, number]> { + return: NumberImpl.Div, Arg1>; +} + +/** + * Full application + */ + +type x = $; // 5 +// ^? +type y = $; +// ~~~ ❌ +type z = $; +// ~~~ ❌ + +/** + * Partial application in order + */ + +type Div1 = $; +type Three = $; +// ^? +type w = $<$, "2">; +// ~~~ ❌ + +/** + * Partial application different order order + */ +type DivBy2 = $; +// ^? +type q = $; // 5 ✅ +// ^? +type r = $<$, 10, 5>; // ✅ +// ^? + +/** + * Higher order + */ + +interface Map extends Fn<[Fn, any[]]> { + return: Args extends [infer fn extends Fn, infer tuple] + ? { [key in keyof tuple]: $ } + : never; +} + +type z2 = $, [2, 4, 6, 8, 10]>; +// ^? + +type ReduceImpl = xs extends [ + infer first, + ...infer rest +] + ? ReduceImpl, rest> + : acc; + +interface Reduce extends Fn<[Fn, any, any[]]> { + return: Args extends [infer fn extends Fn, infer acc, infer tuple] + ? ReduceImpl + : never; +} + +interface Add extends Fn<[number, number]> { + return: NumberImpl.Add, Arg1>; +} + +interface Mul extends Fn<[number, number]> { + return: NumberImpl.Mul, Arg1>; +} + +type reduced1 = $; +// ^? +type reduced2 = $; +// ^? + +type reducedOops = $; +// ~~~~~~ ❌ diff --git a/src/internals/core/impl/MergeArgs.ts b/src/internals/core/impl/MergeArgs.ts index 2873e13..e892aa1 100644 --- a/src/internals/core/impl/MergeArgs.ts +++ b/src/internals/core/impl/MergeArgs.ts @@ -10,6 +10,15 @@ export type ExcludePlaceholders = xs extends [ : ExcludePlaceholders : output; +export type ExcludeUnset = xs extends [ + infer first, + ...infer rest +] + ? Equal extends true + ? ExcludeUnset + : ExcludeUnset + : output; + type MergeArgsRec< pipedArgs extends any[], partialArgs extends any[],