Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add additional object utilities + natural number reifications + Iso module. #99

Open
wants to merge 27 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
0f4137c
feat: implement Object deep-entries utility
poteat Dec 29, 2024
a127200
feat: implement from-entries object util
poteat Dec 29, 2024
8a0f530
feat: implement is-object util
poteat Dec 29, 2024
61fb76a
feat: reify divide-by nat num util
poteat Dec 30, 2024
373a9b9
feat: reify nat num divide util
poteat Dec 30, 2024
915f86a
feat: reify is-even util
poteat Dec 30, 2024
b5cbdcb
feat: reify is-odd nat num util, export intermediary interfaces
poteat Dec 30, 2024
6492548
feat: reify string first and last methods
poteat Jan 2, 2025
071854c
feat: add string rest util
poteat Jan 2, 2025
f348a51
chore: add test case for to-upper util
poteat Jan 2, 2025
1acfe14
feat: reify string init and tail utils
poteat Jan 2, 2025
84a6379
chore: add changelog entry for init / tail
poteat Jan 2, 2025
1b51f03
feat: add 'unwords' util for strings
poteat Jan 3, 2025
c37de4f
feat: add string repeat-by arg-swapped util
poteat Jan 3, 2025
0842d6b
feat: add string repeat-by arg-swapped util
poteat Jan 3, 2025
744aa01
feat: create the 'iso' module for isomorphic bijections
poteat Jan 3, 2025
9bc9842
feat: add the iso.string nested module
poteat Jan 3, 2025
49e19ae
feat: add the chars string isomorphism
poteat Jan 3, 2025
154f207
feat: add words isomorphism
poteat Jan 3, 2025
9bd39b2
chore: add changelog entries for iso module
poteat Jan 3, 2025
83abbd9
feat: add inc/dec isomorphic bijection utils
poteat Jan 3, 2025
fc62d9e
feat: add undigits nat num util
poteat Jan 3, 2025
1ee76f1
feat: add 'digits' isomorphism to iso module
poteat Jan 3, 2025
2bdf02d
feat: add changelog for 0.26.0
poteat Jan 3, 2025
123fcb0
chore: publish 0.26.0
poteat Jan 3, 2025
bb45e04
chore: fix lint errors
poteat Jan 4, 2025
203a337
fix: test case for deep entries util
poteat Jan 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
# Changelog

## [0.26.0]

- Introduce the `Iso` module for isomorphic bijections.
- Add `Iso.String.Chars` to wrap the process of iterating over chars.
- Add `Iso.String.Words` to wrap the process of iterating over words.
- Add `Iso.NaturalNumber.Increment` to wrap the process of incrementing a number.
- Add `Iso.NaturalNumber.Decrement` to wrap the process of decrementing a number.
- Add `Iso.NaturalNumber.Digits` to wrap the process of converting a natural number to a list of digits.
- Add `Object.DeepEntries` to get all deep paths and values in an object.
- Add `Object.FromEntries` to create an object from a list of key-value pairs.
- Add `Object.IsObject` to check if a value is an object.
- Reify `NaturalNumber.DivideBy` to a value-level function.
- Reify `NaturalNumber.Divide` to a value-level function.
- Reify `NaturalNumber.IsEven` to a value-level function.
- Reify `NaturalNumber.IsOdd` to a value-level function.
- Add `NaturalNumber.Undigits` to convert a list of digits to a natural number.
- Reify `String.First` and `String.Last` to value-level functions.
- Reify `String.Init` and `String.Tail` to value-level functions.
- Add `String.Unwords` to join a list of strings with a space delimiter.
- Add `String.RepeatBy` to repeat a string by a given number (argument swapped).

## [0.25.2]

- Fix `List.Sort` to work with 2-ary comparators.
Expand Down
2 changes: 1 addition & 1 deletion pkg/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hkt-toolbelt",
"version": "0.25.2",
"version": "0.26.0",
"description": "Functional and composable type utilities",
"types": "./index.d.ts",
"main": "./index.js",
Expand Down
3 changes: 3 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export * as Digit from './digit'
export * as DigitList from './digit-list'
export * as Function from './function'
export * as Integer from './integer'
export * as Iso from './iso'
export * as Kind from './kind'
export * as List from './list'
export * as Loop from './loop'
Expand All @@ -29,6 +30,7 @@ import * as Digit from './digit'
import * as DigitList from './digit-list'
import * as Function from './function'
import * as Integer from './integer'
import * as Iso from './iso'
import * as Kind from './kind'
import * as List from './list'
import * as Loop from './loop'
Expand All @@ -53,6 +55,7 @@ const _ = {
Digit,
Function,
Integer,
Iso,
Kind,
List,
Loop,
Expand Down
24 changes: 24 additions & 0 deletions src/iso.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export * from './iso/'

/**
* The `Iso` module contains various isomorphisms. These isomorphisms are used
* to transform between different representations of the same type.
*
* Generally, isomorphisms consist of a mapping and an inverse mapping.
* The isomorphism takes in a kind, and returns a new kind where the input is
* transformed via the primary mapping, and the output is transformed via the
* inverse mapping.
*
* A very common operation is to perform a .split(""), do some operations, and
* then .join("") the result. This can be combined into a single step using
* the `Iso` module.
*
* @example
* ```ts
* import { String, Iso } from "hkt-toolbelt";
*
* type T0 = $<Iso.String.Words, $<List.Map, String.Capitalize>>;
* type T1 = $<T0, 'foo bar baz'>; // 'Foo Bar Baz'
* ```
*/
declare module './iso' {}
14 changes: 14 additions & 0 deletions src/iso/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export * as NaturalNumber from './natural-number'
export * as String from './string'

import * as NaturalNumber from './natural-number'
import * as String from './string'

const _ = {
NaturalNumber: NaturalNumber,
String: String
}

type _ = typeof _

export default _
16 changes: 16 additions & 0 deletions src/iso/natural-number.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export * from './natural-number/'

/**
* The `Iso.NaturalNumber` module contains various number-related isomorphisms.
* These first compute some transformation on the input, and then apply the
* inverse transformation to the output.
*
* @example
* ```ts
* import { Iso } from "hkt-toolbelt";
*
* type T0 = $<Iso.NaturalNumber.Increment, $<NaturalNumber.Multiply, 2>>;
* type T1 = $<T0, 10>; // (N + 1) * 2 - 1 = 21
* ```
*/
declare module './natural-number' {}
15 changes: 15 additions & 0 deletions src/iso/natural-number/decrement.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { $, Iso, NaturalNumber, Test } from '../..'

type Decrement_Spec = [
/**
* Can wrap a kind i.e. f(n - 1) + 1, for f(x) = x * 2
*/
Test.Expect<
$<$<Iso.NaturalNumber.Decrement, $<NaturalNumber.Multiply, 2>>, 10>,
19
>
]

it('should wrap a kind i.e. f(n - 1) + 1, for f(x) = x * 2', () => {
expect(Iso.NaturalNumber.decrement(NaturalNumber.multiply(2))(10)).toBe(19)
})
58 changes: 58 additions & 0 deletions src/iso/natural-number/decrement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { $, Type, Kind, NaturalNumber } from '../..'

/**
* Given a kind, return an isomorphism such that the input is decremented by
* one, and the output is incremented by one.
*
* @param {Kind.Kind} K - The kind to wrap with an increment/decrement.
*
* @example
* ```ts
* import { Iso } from "hkt-toolbelt";
*
* type T0 = Iso.NaturalNumber._$decrement<$<NaturalNumber.Multiply, 2>>;
* type T1 = $<T0, 10>; // (N - 1) * 2 + 1 = 19
* ```
*/
export type _$decrement<K extends Kind.Kind> = $<
Kind.Pipe,
[NaturalNumber.Decrement, K, NaturalNumber.Increment]
>

/**
* Given a kind, return an isomorphism such that the input is decremented by
* one, and the output is incremented by one.
*
* @param {Kind.Kind} K - The kind to wrap with an increment/decrement.
*
* @example
* ```ts
* import { Iso } from "hkt-toolbelt";
*
* type T0 = $<Iso.NaturalNumber.Decrement, $<NaturalNumber.Multiply, 2>>;
* type T1 = $<T0, 10>; // (N - 1) * 2 + 1 = 19
* ```
*/
export interface Decrement extends Kind.Kind {
f(x: Type._$cast<this[Kind._], Kind.Kind>): _$decrement<typeof x>
}

/**
* Given a kind, return an isomorphism such that the input is decremented by
* one, and the output is incremented by one.
*
* @param {Kind.Kind} K - The kind to wrap with an increment/decrement.
*
* @example
* ```ts
* import { Iso } from "hkt-toolbelt";
*
* const T0 = Iso.NaturalNumber.decrement(NaturalNumber.multiply(2));
* const T1 = T0(10); // (N - 1) * 2 + 1 = 19
* ```
*/
export const decrement = ((f: Kind._$reify<Kind.Kind<(x: number) => number>>) =>
(x: number) =>
NaturalNumber.increment(
f(NaturalNumber.decrement(x))
)) as Kind._$reify<Decrement>
22 changes: 22 additions & 0 deletions src/iso/natural-number/digits.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { $, Iso, NaturalNumber, Test, List } from '../..'

type Digits_Spec = [
/**
* Can convert a natural number to a list of digits.
*/
Test.Expect<
$<
$<Iso.NaturalNumber.Digits, $<List.Map, $<NaturalNumber.Multiply, 2>>>,
99
>,
1818
>
]

it('should convert a natural number to a list of digits', () => {
const result = Iso.NaturalNumber.digits(List.map(NaturalNumber.multiply(2)))(
99
)

expect(result).toBe(1818)
})
65 changes: 65 additions & 0 deletions src/iso/natural-number/digits.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { $, Type, Kind, NaturalNumber, Number } from '../..'

/**
* Given a kind, return an isomorphism such that the input is converted to a
* list of digits, and the output is converted from a list of digits back to a
* natural number.
*
* @param {Kind.Kind} K - The kind to convert to a natural number.
*
* @example
* ```ts
* import { Iso } from "hkt-toolbelt";
*
* type T0 = Iso.NaturalNumber._$digits<$<List.Map<$<NaturalNumber.Multiply, 2>>>;
* type T1 = $<T0, 99>; // 1818
* ```
*/
export type _$digits<
K extends Kind.Kind<(x: Number.Number[]) => Number.Number[]>
> = $<Kind.Pipe, [NaturalNumber.Digits, K, NaturalNumber.Undigits]>

/**
* Given a kind, return an isomorphism such that the input is converted to a
* list of digits, and the output is converted from a list of digits back to a
* natural number.
*
* @param {Kind.Kind} K - The kind to convert to a natural number.
*
* @example
* ```ts
* import { Iso } from "hkt-toolbelt";
*
* type T0 = $<Iso.NaturalNumber.Digits, $<List.Map, $<NaturalNumber.Multiply, 2>>>
* type T1 = $<T0, 99>; // 1818
* ```
*/
export interface Digits extends Kind.Kind {
f(
x: Type._$cast<
this[Kind._],
Kind.Kind<(x: Number.Number[]) => Number.Number[]>
>
): _$digits<typeof x>
}

/**
* Given a kind, return an isomorphism such that the input is converted to a
* list of digits, and the output is converted from a list of digits back to a
* natural number.
*
* @param {Kind.Kind} K - The kind to convert to a natural number.
*
* @example
* ```ts
* import { Iso } from "hkt-toolbelt";
*
* const T0 = Iso.NaturalNumber.digits(List.map(NaturalNumber.multiply(2)));
* const T1 = T0(99); // 1818
* ```
*/
export const digits = ((
f: Kind._$reify<Kind.Kind<(x: Number.Number[]) => number[]>>
) =>
(x: number) =>
NaturalNumber.undigits(f(NaturalNumber.digits(x)))) as Kind._$reify<Digits>
15 changes: 15 additions & 0 deletions src/iso/natural-number/increment.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { $, Iso, NaturalNumber, Test } from '../..'

type Increment_Spec = [
/**
* Can wrap a kind i.e. f(n + 1) - 1, for f(x) = x * 2
*/
Test.Expect<
$<$<Iso.NaturalNumber.Increment, $<NaturalNumber.Multiply, 2>>, 10>,
21
>
]

it('should wrap a kind i.e. f(n + 1) - 1, for f(x) = x * 2', () => {
expect(Iso.NaturalNumber.increment(NaturalNumber.multiply(2))(10)).toBe(21)
})
58 changes: 58 additions & 0 deletions src/iso/natural-number/increment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { $, Type, Kind, NaturalNumber } from '../..'

/**
* Given a kind, return an isomorphism such that the input is incremented by
* one, and the output is decremented by one.
*
* @param {Kind.Kind} K - The kind to wrap with an increment/decrement.
*
* @example
* ```ts
* import { Iso } from "hkt-toolbelt";
*
* type T0 = Iso.NaturalNumber._$increment<$<NaturalNumber.Multiply, 2>>;
* type T1 = $<T0, 10>; // (N + 1) * 2 - 1 = 21
* ```
*/
export type _$increment<K extends Kind.Kind> = $<
Kind.Pipe,
[NaturalNumber.Increment, K, NaturalNumber.Decrement]
>

/**
* Given a kind, return an isomorphism such that the input is incremented by
* one, and the output is decremented by one.
*
* @param {Kind.Kind} K - The kind to wrap with an increment/decrement.
*
* @example
* ```ts
* import { Iso } from "hkt-toolbelt";
*
* type T0 = $<Iso.NaturalNumber.Increment, $<NaturalNumber.Multiply, 2>>;
* type T1 = $<T0, 10>; // (N + 1) * 2 - 1 = 21
* ```
*/
export interface Increment extends Kind.Kind {
f(x: Type._$cast<this[Kind._], Kind.Kind>): _$increment<typeof x>
}

/**
* Given a kind, return an isomorphism such that the input is incremented by
* one, and the output is decremented by one.
*
* @param {Kind.Kind} K - The kind to wrap with an increment/decrement.
*
* @example
* ```ts
* import { Iso } from "hkt-toolbelt";
*
* const T0 = Iso.NaturalNumber.increment(NaturalNumber.multiply(2));
* const T1 = T0(10); // (N + 1) * 2 - 1 = 21
* ```
*/
export const increment = ((f: Kind._$reify<Kind.Kind<(x: number) => number>>) =>
(x: number) =>
NaturalNumber.decrement(
f(NaturalNumber.increment(x))
)) as Kind._$reify<Increment>
3 changes: 3 additions & 0 deletions src/iso/natural-number/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './decrement'
export * from './digits'
export * from './increment'
16 changes: 16 additions & 0 deletions src/iso/string.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export * from './string/'

/**
* The `Iso.String` module contains various string-related isomorphisms. These
* isomorphisms are used to transform between different representations of
* strings.
*
* @example
* ```ts
* import { String, Iso } from "hkt-toolbelt";
*
* type T0 = $<Iso.String.Words, $<List.Map, String.Capitalize>>;
* type T1 = $<T0, 'foo bar baz'>; // 'Foo Bar Baz'
* ```
*/
declare module './string' {}
15 changes: 15 additions & 0 deletions src/iso/string/chars.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { $, Iso, String, Test, List } from '../..'

type Chars_Spec = [
/**
* Can repeat each character of a string by two.
*/
Test.Expect<
$<$<Iso.String.Chars, $<List.Map, $<String.RepeatBy, 2>>>, 'bar'>,
'bbaarr'
>
]

it('should repeat each character of a string by two', () => {
expect(Iso.String.chars(List.map(String.repeatBy(2)))('bar')).toBe('bbaarr')
})
Loading
Loading