Skip to content

Commit

Permalink
Add Tuple.map (#3658)
Browse files Browse the repository at this point in the history
Co-authored-by: maksim.khramtsov <maksim.khramtsov@btsdigital.kz>
  • Loading branch information
2 people authored and tim-smart committed Oct 6, 2024
1 parent 7b3150f commit 5b36494
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 0 deletions.
19 changes: 19 additions & 0 deletions .changeset/strong-pans-flash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
"effect": minor
---

`Tuple.map` transforms each element of tuple using the given function, treating tuple homomorphically

```ts
import { pipe, Tuple } from "effect"

const result = pipe(
// ^? [string, string, string]
["a", 1, false] as const,
T.map((el) => {
//^? "a" | 1 | false
return el.toString().toUppercase()
})
)
assert.deepStrictEqual(result, ["A", "1", "FALSE"])
```
22 changes: 22 additions & 0 deletions packages/effect/dtslint/Tuple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,25 @@ pipe(hole<Array<number>>(), T.at(1))

// $ExpectType number
pipe(hole<Array<number>>(), T.at(-1))

// -------------------------------------------------------------------------------------
// map
// -------------------------------------------------------------------------------------

// $ExpectType [false, false, false]
pipe(
T.make("a", 1),
T.appendElement(true),
T.map((x) => {
// $ExpectType string | number | boolean
x
return false as const
})
)

// $ExpectType [false, false, false]
T.map(["a", 1, false], (x) => {
// $ExpectType string | number | boolean
x
return false as const
})
35 changes: 35 additions & 0 deletions packages/effect/src/Tuple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as Equivalence from "./Equivalence.js"
import { dual } from "./Function.js"
import type { TypeLambda } from "./HKT.js"
import * as order from "./Order.js"
import type { TupleOf } from "./Types.js"

/**
* @category type lambdas
Expand Down Expand Up @@ -61,6 +62,40 @@ export const getFirst = <L, R>(self: readonly [L, R]): L => self[0]
*/
export const getSecond = <L, R>(self: readonly [L, R]): R => self[1]

/**
* Transforms each element of tuple using the given function, treating tuple homomorphically
*
* @param self - A tuple.
* @param f - The function to transform elements of the tuple.
*
* @example
* import { pipe, Tuple } from "effect"
*
* const result = pipe(
* ["a", 1, false] as const,
* Tuple.map((el) => el.toString().toUpperCase())
* )
* assert.deepStrictEqual(result, ['A', '1', 'FALSE'])
*
* @category mapping
* @since 3.9.0
*/
export const map: {
<T extends ReadonlyArray<any> | [], B>(
fn: (element: T[number]) => B
): (self: T) => TupleOf<T["length"], B>
<B, T extends ReadonlyArray<any> | []>(
self: T,
fn: (element: T[number]) => B
): TupleOf<T["length"], B>
} = dual(
2,
<N extends number, A, B>(
self: TupleOf<N, A>,
fn: (element: A) => B
): TupleOf<N, B> => self.map((element) => fn(element)) as TupleOf<N, B>
)

/**
* Transforms both elements of a tuple using the given functions.
*
Expand Down
4 changes: 4 additions & 0 deletions packages/effect/test/Tuple.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ describe("Tuple", () => {
})).toEqual(["a!", 2])
})

it("map", () => {
expect(T.map(["a", 1, false], (x) => x.toString().toUpperCase())).toEqual(["A", "1", "FALSE"])
})

it("swap", () => {
expect(T.swap(T.make("a", 1))).toEqual([1, "a"])
})
Expand Down

0 comments on commit 5b36494

Please sign in to comment.