hkt-toolbelt
Version:
Functional and composable type utilities
74 lines (73 loc) • 2.27 kB
TypeScript
import { $, $N, Kind, NaturalNumber, Conditional, List, Function } from '..';
/**
* Check whether a natural number `N` is divisible by another number `M`.
*
* i.e. determine whether `N % M === 0`.
*
* @template M - The number to divide by.
* @template N - The number to check divisibility for.
*
* This function 'lifts' the modulo parameters (M and N) out of the pipe via
* the curry and uncurry operators.
*
* For optimal performance, this should be implemented as a 'native' type-level
* function - however this example is pedagogically valuable for demonstrating
* the lifting technique.
*/
type DivisibleBy = $N<Kind.Curry, [
2,
$<Kind.Pipe, [
$<Kind.Uncurry, NaturalNumber.ModuloBy>,
$<Conditional.Equals, 0>
]>
]>;
/**
* A type-level function that returns "FizzBuzz" if the input is divisible by
* both 3 and 5, "Fizz" if the input is divisible by 3, "Buzz" if the input is
* divisible by 5, and the input otherwise.
*
* This function uses the `Conditional.If` type-level function to encode an
* if-then-else statement.
*
* @template N - The number to compute the FizzBuzz result for.
*
* @example
* ```ts
* import { $, NaturalNumberTheory } from "hkt-toolbelt"
*
* type R15 = $<NaturalNumberTheory.FizzBuzz, 15> // "FizzBuzz"
* type R4 = $<NaturalNumberTheory.FizzBuzz, 4> // 4
* ```
*/
export type FizzBuzz = $N<Conditional.If, [
$<DivisibleBy, 15>,
$<Function.Constant, 'FizzBuzz'>,
$N<Conditional.If, [
$<DivisibleBy, 3>,
$<Function.Constant, 'Fizz'>,
$N<Conditional.If, [
$<DivisibleBy, 5>,
$<Function.Constant, 'Buzz'>,
Function.Identity
]>
]>
]>;
/**
* A type-level function that returns a list of the FizzBuzz results for the
* first `N` natural numbers, from 1 to `N` inclusive.
*
* @template N - The number of FizzBuzz results to compute.
*
* @example
* ```ts
* import { $, NaturalNumberTheory } from "hkt-toolbelt"
*
* // ["1", "2", "Fizz", "4", "Buzz", "Fizz", "7", "8", "Fizz", "Buzz"]
* type R10 = $<NaturalNumberTheory.FizzBuzzSequence, 10>
* ```
*/
export type FizzBuzzSequence = $<Kind.Pipe, [
List.Times,
$<List.Map, $<Kind.Pipe, [NaturalNumber.Increment, FizzBuzz]>>
]>;
export {};