ts-nat-comm/test.ts
2023-04-20 19:51:20 -05:00

131 lines
3 KiB
TypeScript

import {} from "./typeLevelNats";
type GenericFunction = (...x: never[]) => unknown;
type Assume<T, U> = T extends U ? T : U;
abstract class TypeFunc<Arg, Ret> {
readonly _1?: unknown;
new: (_: Arg) => Ret;
}
type Apply<Arg, Ret, F extends TypeFunc<Arg, Ret>, _1> = ReturnType<
(F & {
readonly _1: _1;
})["new"]
>;
interface GetPrev<N extends Nat> extends TypeFunc<Suc<N>, N> {
new: (arg: Suc<N>) => N;
}
// nat-elim : (M : T -> U) -> (cz : M z) -> (sz : (n : N) -> M n -> M (suc n)) -> (n : N) -> M n
// (M : T -> U) -> (cz : M z) -> (sz : (n : N) -> M n -> M (suc n)) -> (n : N) -> M n
//
interface ConstNat extends TypeFunc<any, Nat> {
new: (_: any) => Nat;
}
interface DoubleSuc extends TypeFunc<Nat, Nat> {
new: (arg: Assume<this["_1"], Nat>) => Suc<Suc<typeof arg>>;
}
type NatElim0<
M extends TypeFunc<Nat, any>,
ZCase,
SCase extends TypeFunc<
Nat,
TypeFunc<Apply<Nat, any, M, Nat>, Apply<Nat, any, M, Suc<Nat>>>
>,
N
> =
/** --------------------------------------------------------------- */
N extends Zero // // if N matches Zero
? ZCase // return ZCase
: N extends Suc<infer Prev> // if N matches Suc(Prev)
? Apply<
any /* TODO: */,
any /* TODO: */,
Apply<
Nat,
TypeFunc<Apply<Nat, any, M, Nat>, Apply<Nat, any, M, Suc<Nat>>>,
SCase,
Prev
>,
Apply<Nat, any, M, Prev>
>
: never;
interface DoubleNat extends TypeFunc<Nat, Nat> {
new: (arg: Nat) => NatElim0<ConstNat, Zero, DoubleSuc, typeof arg>;
}
/*
interface NatElim<
MRet,
M extends TypeFunc<Nat, MRet>,
ZCase extends Apply<infer A, infer R, M<A, R>, Z>,
SCase extends TypeFunc
> extends TypeFunc {
_unused: (_1: ZCase, _2: SCase) => never;
new: (arg: Assume<this["_1"], Nat>) => Apply<M, typeof arg>;
}
type Two = S<S<Z>>;
const realThree: S<S<S<Z>>> = S.s();
const realFour: S<S<S<S<Z>>>> = S.s();
function isFour<F extends Apply<DoubleNat, Two>>(_: F) {}
isFour(realThree);
isFour(realFour);
*/
/////
type Length<T extends any[]> = T extends { length: infer L } ? L : never;
type BuildTuple<L extends number, T extends any[] = []> = T extends {
length: L;
}
? T
: BuildTuple<L, [...T, any]>;
type Add<A extends number, B extends number> = Length<
[...BuildTuple<A>, ...BuildTuple<B>]
>;
type Equals<T, T1 extends T, T2 extends T> = { eq: [T1, T2] };
type Seven = Add<3, 4>; // 7
function isSeven(s: Seven) {}
isSeven(6);
isSeven(7);
///
class Eq<A, B> {
private a: (_: A) => A;
private b: (_: B) => B;
private constructor() {}
static refl<T>(): Eq<T, T> {
return new Eq();
}
}
function isEqual1(_: Eq<3, 3>) {}
isEqual1(Eq.refl());
function isEqual2(_: Eq<3, 4>) {}
isEqual2(Eq.refl());
function isEqual3(_: Eq<Add<3, 4>, 7>) {}
isEqual3(Eq.refl());
function isEqual4(_: Eq<Add<3, 4>, 8>) {}
isEqual4(Eq.refl());
///
type Commutative<A extends number, B extends number> = Eq<Add<A, B>, Add<B, A>>;
function comm<A extends number, B extends number>(): Commutative<A, B> {
return Eq.refl();
}