-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #55 from MajorLift/jongsun/util/230815-kind-apply-n
Add Kind util `ApplyN`, and derived List methods
- Loading branch information
Showing
13 changed files
with
578 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import { | ||
$, | ||
$N, | ||
Kind, | ||
Function, | ||
Conditional, | ||
List, | ||
String, | ||
Test | ||
} from 'hkt-toolbelt' | ||
|
||
type ApplyN_Spec = [ | ||
/** | ||
* Can apply kinds to types. | ||
*/ | ||
Test.Expect< | ||
$<$<Kind.ApplyN, [Function.Identity, [number]]>, List.Map>, | ||
[number] | ||
>, | ||
|
||
/** | ||
* Can apply never | ||
*/ | ||
Test.Expect<$<$<Kind.ApplyN, [never]>, Function.Identity>, never>, | ||
Test.Expect< | ||
$< | ||
$<Kind.ApplyN, [never]>, | ||
$N< | ||
Conditional.If, | ||
[ | ||
$<Conditional.Extends, never>, | ||
$<Function.Constant, true>, | ||
$<Function.Constant, false> | ||
] | ||
> | ||
>, | ||
true | ||
>, | ||
|
||
/** | ||
* Can be used in its partially applied form. | ||
*/ | ||
Test.Expect< | ||
$N< | ||
List.Map, | ||
[ | ||
$< | ||
$<Kind.ApplyN, [$<Function.Constant, null>]>, | ||
$N<Conditional.If, [$<Conditional.Equals, 1>, Function.Identity]> | ||
>, | ||
$<List.Times, 3> | ||
] | ||
>, | ||
[null, 1, null] | ||
>, | ||
|
||
/** | ||
* Can loop through a list of kinds and apply them to an input. | ||
*/ | ||
Test.Expect< | ||
$< | ||
$<List.Map, $<Kind.ApplyN, ['qux']>>, | ||
[$<String.Prepend, 'foo'>, $<String.Append, 'bar'>, String.ToUpper] | ||
>, | ||
['fooqux', 'quxbar', 'QUX'] | ||
>, | ||
|
||
Test.Expect< | ||
$N< | ||
List.Map, | ||
[ | ||
$<Kind.Apply, number | symbol>, | ||
$N< | ||
List.Map, | ||
[ | ||
$< | ||
Kind.ApplyN, | ||
[$<Function.Constant, true>, $<Function.Constant, false>] | ||
>, | ||
[ | ||
$<Conditional.If, $<Conditional.Extends, never>>, | ||
$<Conditional.If, $<Conditional.Extends, string>>, | ||
$<Conditional.If, $<Conditional.Extends, number | symbol>> | ||
] | ||
] | ||
> | ||
] | ||
>, | ||
[false, false, true] | ||
>, | ||
|
||
Test.Expect< | ||
$N< | ||
List.Map, | ||
[ | ||
$<$<Kind.ApplyN, [0, 1, ['new']]>, List.Splice>, | ||
[['old', 1, 2], ['old', 3, 4]] | ||
] | ||
>, | ||
[['new', 1, 2], ['new', 3, 4]] | ||
>, | ||
|
||
/** | ||
* $ enforces list inputs. | ||
*/ | ||
// @ts-expect-error | ||
$<$<Kind.Apply, number>, String.StartsWith<'foo'>>, | ||
|
||
/** | ||
* $ will emit an error on non-kinds. | ||
*/ | ||
// @ts-expect-error | ||
$<$<Kind.Apply, [number]>, number> | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { $, Kind, List, Test } from '..' | ||
|
||
type Arity_Spec = [ | ||
/** | ||
* Returns empty tuple for fully applied function | ||
*/ | ||
Test.Expect<$<Kind.Arity, $<$<$<List.Reduce, never>, never>, never>>, 0>, | ||
|
||
/** | ||
* Returns tuple of length one for partially applied function expecting one more argument. | ||
*/ | ||
Test.Expect<$<Kind.Arity, $<$<List.Reduce, never>, never>>, 1>, | ||
|
||
/** | ||
* Returns tuple of length two for partially applied function expecting two more arguments. | ||
*/ | ||
Test.Expect<$<Kind.Arity, $<List.Reduce, never>>, 2>, | ||
|
||
/** | ||
* Returns tuple of length three for 3-ary function. | ||
*/ | ||
Test.Expect<$<Kind.Arity, List.Reduce>, 3>, | ||
|
||
/** | ||
* Returns empty tuple for fully applied function | ||
*/ | ||
Test.Expect< | ||
$<Kind.Arity, $<$<$<$<List.Splice, never>, never>, never>, never>>, | ||
0 | ||
>, | ||
|
||
/** | ||
* Returns tuple of length one for partially applied function expecting one more argument. | ||
*/ | ||
Test.Expect<$<Kind.Arity, $<$<$<List.Splice, never>, never>, never>>, 1>, | ||
|
||
/** | ||
* Returns tuple of length two for partially applied function expecting two more arguments. | ||
*/ | ||
Test.Expect<$<Kind.Arity, $<$<List.Splice, never>, never>>, 2>, | ||
|
||
/** | ||
* Returns tuple of length three for partially applied function expecting three more arguments. | ||
*/ | ||
Test.Expect<$<Kind.Arity, $<List.Splice, never>>, 3>, | ||
|
||
/** | ||
* Returns tuple of length four for 4-ary function. | ||
*/ | ||
Test.Expect<$<Kind.Arity, List.Splice>, 4>, | ||
|
||
/** | ||
* Emits error for non-kind input | ||
*/ | ||
// @ts-expect-error | ||
Test.Expect<$<Kind.Arity, number>, never> | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { $, Kind, Type, Number, NaturalNumber } from '..' | ||
|
||
/** | ||
* `_$arity` is a type-level function that takes in a curried type-level function, | ||
* and returns the total number of arguments it needs in order to be fully applied. | ||
* | ||
* @template {Kind.Kind} K - A type-level function whose arity will be returned. | ||
* @returns {Number.Number} The number of arguments that `K` can be successively applied to. | ||
* | ||
* If `K` is a fully-applied `Kind`, 0 will be returned. | ||
* If `K` is not a `Kind`, an error will be emitted. | ||
*/ | ||
export type _$arity< | ||
K extends Kind.Kind, | ||
ACC extends Number.Number = 0 | ||
> = Kind._$inputOf<K> extends never | ||
? ACC | ||
: $<K, never> extends Kind.Kind | ||
? _$arity<$<K, never>, NaturalNumber._$increment<ACC>> | ||
: never | ||
|
||
/** | ||
* `Arity` is a type-level function that takes in a curried type-level function, | ||
* and returns the total number of arguments it needs in order to be fully applied. | ||
* | ||
* @template {Kind.Kind} K - A type-level function whose arity will be returned. | ||
* @returns {Number.Number} The number of arguments that `K` can be successively applied to. | ||
* | ||
* If `K` is a fully-applied `Kind`, 0 will be returned. | ||
* If `K` is not a `Kind`, an error will be emitted. | ||
* | ||
* @example | ||
* type ReduceArity = $<Kind.Arity, List.Reduce> // 3 | ||
* type PartialApply1 = $<Kind.Arity, $<List.Reduce, never>> // 2 | ||
* type PartialApply2 = $<Kind.Arity, $<$<List.Reduce, never>, never>> // 1 | ||
* type FullApply = $<Kind.Arity, $<$<$<List.Reduce, never>, never>, never>> // 0 | ||
*/ | ||
export interface Arity extends Kind.Kind { | ||
f(x: Type._$cast<this[Kind._], Kind.Kind>): _$arity<typeof x> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import { $, Kind, List, Number, Test } from '..' | ||
|
||
type Parameters_Spec = [ | ||
/** | ||
* Returns empty tuple for fully applied function | ||
*/ | ||
Test.Expect< | ||
$<Kind.Parameters, $<$<$<List.Reduce, never>, never>, never>>, | ||
[] | ||
>, | ||
|
||
/** | ||
* Returns tuple of length one for partially applied function expecting one more argument. | ||
*/ | ||
Test.Expect<$<Kind.Parameters, $<$<List.Reduce, never>, never>>, [List.List]>, | ||
|
||
/** | ||
* Returns tuple of length two for partially applied function expecting two more arguments. | ||
*/ | ||
Test.Expect<$<Kind.Parameters, $<List.Reduce, never>>, [unknown, List.List]>, | ||
|
||
/** | ||
* Returns tuple of length three for 3-ary function. | ||
*/ | ||
Test.Expect< | ||
$<Kind.Parameters, List.Reduce>, | ||
[Kind.Kind<(x: never) => Kind.Kind>, unknown, List.List] | ||
>, | ||
|
||
/** | ||
* Returns empty tuple for fully applied function | ||
*/ | ||
Test.Expect< | ||
$<Kind.Parameters, $<$<$<$<List.Splice, never>, never>, never>, never>>, | ||
[] | ||
>, | ||
|
||
/** | ||
* Returns tuple of length one for partially applied function expecting one more argument. | ||
*/ | ||
Test.Expect< | ||
$<Kind.Parameters, $<$<$<List.Splice, never>, never>, never>>, | ||
[List.List] | ||
>, | ||
|
||
/** | ||
* Returns tuple of length two for partially applied function expecting two more arguments. | ||
*/ | ||
Test.Expect< | ||
$<Kind.Parameters, $<$<List.Splice, never>, never>>, | ||
[List.List, List.List] | ||
>, | ||
|
||
/** | ||
* Returns tuple of length three for partially applied function expecting three more arguments. | ||
*/ | ||
Test.Expect< | ||
$<Kind.Parameters, $<List.Splice, never>>, | ||
[Number.Number, List.List, List.List] | ||
>, | ||
|
||
/** | ||
* Returns tuple of length four for 4-ary function. | ||
*/ | ||
Test.Expect< | ||
$<Kind.Parameters, List.Splice>, | ||
[Number.Number, Number.Number, List.List, List.List] | ||
>, | ||
|
||
/** | ||
* Emits error for non-kind input | ||
*/ | ||
// @ts-expect-error | ||
Test.Expect<$<Kind.Parameters, number>, never> | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { $, Kind, Type, List } from '..' | ||
|
||
/** | ||
* `_$parameters` is a type-level function that takes in a curried n-ary type-level function, | ||
* and returns an ordered list of the types of the n arguments that the input function is expecting. | ||
* | ||
* @template {Kind.Kind} K - A type-level function whose parameters will be returned. | ||
* @returns {List.List} A list of the types of the arguments that `K` can be successively applied to. | ||
* | ||
* `K` can be applied successively to a series of arguments that extend each element of the | ||
* list returned by `_$parameters` by using the @see {@link `$`} operator. | ||
* | ||
* `K` can also be applied to a list of arguments that extends the list returend by `_$parameters` | ||
* by using the @see {@link `$N`} operator. | ||
* | ||
* If `K` is a fully-applied `Kind`, an empty list will be returned. | ||
* If `K` is not a `Kind`, an error will be emitted. | ||
*/ | ||
export type _$parameters< | ||
K extends Kind.Kind, | ||
ACC extends List.List = [] | ||
> = Kind._$inputOf<K> extends never | ||
? ACC | ||
: $<K, never> extends Kind.Kind | ||
? _$parameters<$<K, never>, List._$push<Kind._$inputOf<K>, ACC>> | ||
: never | ||
|
||
/** | ||
* `Parameters` is a type-level function that takes in a curried n-ary type-level function, | ||
* and returns an ordered of the types of the n arguments that the input function is expecting. | ||
* | ||
* @template {Kind.Kind} K - A type-level function whose parameters will be returned. | ||
* @returns {List.List} A list of the types of the arguments that `K` can be successively applied to. | ||
* | ||
* `K` can be applied successively to a series of arguments that extend each element of the | ||
* list returned by `Parameters` by using the @see {@link `$`} operator. | ||
* | ||
* `K` can also be applied to a list of arguments that extends the list returend by `Parameters` | ||
* by using the @see {@link `$N`} operator. | ||
* | ||
* If `K` is a fully-applied `Kind`, an empty list will be returned. | ||
* If `K` is not a `Kind`, an error will be emitted. | ||
* | ||
* @example | ||
* type ReduceParams = $<Kind.Parameters, List.Reduce> // [Kind.Kind<(x: never) => Kind.Kind>, unknown, List.List] | ||
* type PartialApply1 = $<Kind.Parameters, $<List.Reduce, never>> // [unknown, List.List] | ||
* type PartialApply2 = $<Kind.Parameters, $<$<List.Reduce, never>, never>> // [List.List] | ||
* type FullApply = $<Kind.Parameters, $<$<$<List.Reduce, never>, never>, never>> // [] | ||
*/ | ||
export interface Parameters extends Kind.Kind { | ||
f(x: Type._$cast<this[Kind._], Kind.Kind>): _$parameters<typeof x> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.