rivo
Version:
🤖 The ultimate library you need for composable type-level programming in TypeScript, powered by HKT.
54 lines (50 loc) • 1.7 kB
TypeScript
import type { Nat } from ".";
import type { _AddDigit } from "./internal/_AddDigit";
import type { _CompareStrLength } from "./internal/_CompareStrLength";
import type { Digit } from "..";
import type { Arg0, Arg1, Fn } from "../../HKT";
import type { Reverse } from "../../Str/Reverse";
import type { GT } from "../../typeclass/Ord";
import type { _StrToNum } from "../internal/_StrToNum";
/**
* Add two {@link Nat}s.
*
* Sig: `(n: Nat, m: Nat) => Nat`
*/
export type Add<N extends Nat, M extends Nat> = _StrToNum<SAdd<`${N}`, `${M}`>>;
/**
* Add two string representations of {@link Nat}s.
* @private
*/
type SAdd<N extends string, M extends string> =
_CompareStrLength<N, M> extends GT ? Reverse<_SAdd<Reverse<N>, Reverse<M>>>
: Reverse<_SAdd<Reverse<M>, Reverse<N>>>;
type _SAdd<
N extends string,
M extends string,
Carry extends 0 | 1 = 0,
Result extends string = "",
> =
N extends `${infer F extends Digit}${infer R}` ?
M extends `${infer G extends Digit}${infer S}` ?
_AddDigit<F, G> extends infer D extends Nat ?
`${D}` extends `1${infer D extends Digit}` ?
_SAdd<R, S, 1, `${Result}${Carry extends 1 ? _AddDigit<D, 1> : D}`>
: D extends Digit ?
[D, Carry] extends [9, 1] ?
_SAdd<R, S, 1, `${Result}0`>
: _SAdd<R, S, 0, `${Result}${Carry extends 1 ? _AddDigit<D, 1> : D}`>
: never
: never
: Carry extends 1 ? `${Result}${_SAdd<N, "1">}`
: `${Result}${N}`
: Carry extends 1 ? `${Result}1`
: Result;
/**
* [Fn] Add two {@link Nat}s.
*
* Sig: `(n: Nat, m: Nat) => Nat`
*/
export default interface AddFn extends Fn<[Nat, Nat], Nat> {
def: () => Add<Arg0<this>, Arg1<this>>;
}