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

version 0.0.5 #18

Merged
merged 12 commits into from
Oct 17, 2022
5 changes: 5 additions & 0 deletions .changeset/four-singers-sing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@fp-ts/core": patch
---

Semigroup: fix reverse implementation
5 changes: 5 additions & 0 deletions .changeset/fuzzy-mugs-hope.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@fp-ts/core": patch
---

Foldable / FoldableWithIndex: add compositions
5 changes: 5 additions & 0 deletions .changeset/khaki-goats-flash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@fp-ts/core": patch
---

Foldable / FlodableWithIndex: curry toReadonlyArrayWith and add toReadonlyArray
5 changes: 5 additions & 0 deletions .changeset/short-radios-melt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@fp-ts/core": patch
---

add FunctorWithIndex module
5 changes: 5 additions & 0 deletions .changeset/thin-moles-tell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@fp-ts/core": patch
---

Semigroupal: remove useless zipWith export
5 changes: 5 additions & 0 deletions .changeset/thirty-nails-end.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@fp-ts/core": patch
---

Bounded: swap maximum, minimum arguments in fromSortable
7 changes: 4 additions & 3 deletions src/Bounded.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ import type { Sortable } from "@fp-ts/core/Sortable"
* @since 1.0.0
*/
export interface Bounded<A> extends Sortable<A> {
readonly maximum: A
readonly minimum: A
readonly maximum: A
}

/**
* @category constructors
* @since 1.0.0
*/
export const fromSortable = <A>(Sortable: Sortable<A>, maximum: A, minimum: A): Bounded<A> => ({
export const fromSortable = <A>(Sortable: Sortable<A>, minimum: A, maximum: A): Bounded<A> => ({
...Sortable,
maximum,
minimum
Expand All @@ -28,7 +28,8 @@ export const fromSortable = <A>(Sortable: Sortable<A>, maximum: A, minimum: A):
*
* @since 1.0.0
*/
export const clamp = <A>(B: Bounded<A>): (a: A) => A => compare.clamp(B)(B.minimum, B.maximum)
export const clamp = <A>(Bounded: Bounded<A>): (a: A) => A =>
compare.clamp(Bounded)(Bounded.minimum, Bounded.maximum)

/**
* Reverses the `Ord` of a `Bounded` and flips `maximum` and `minimum` values.
Expand Down
50 changes: 44 additions & 6 deletions src/Foldable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/

import type { Kind, TypeClass, TypeLambda } from "@fp-ts/core/HKT"
import { identity, pipe } from "@fp-ts/core/internal/Function"
import type { Monoid } from "@fp-ts/core/Monoid"

/**
Expand All @@ -21,17 +22,54 @@ export interface Foldable<F extends TypeLambda> extends TypeClass<F> {
) => <S, R, O, E>(self: Kind<F, S, R, O, E, A>) => B
}

/**
* Returns a default `reduce` composition.
*
* @since 1.0.0
*/
export const reduceComposition = <F extends TypeLambda, G extends TypeLambda>(
F: Foldable<F>,
G: Foldable<G>
) =>
<B, A>(b: B, f: (b: B, a: A) => B) =>
<FS, FR, FO, FE, GS, GR, GO, GE>(
self: Kind<F, FS, FR, FO, FE, Kind<G, GS, GR, GO, GE, A>>
): B => pipe(self, F.reduce(b, (b, ga) => pipe(ga, G.reduce(b, f))))

/**
* Returns a default `reduceRight` composition.
*
* @since 1.0.0
*/
export const reduceRightComposition = <F extends TypeLambda, G extends TypeLambda>(
F: Foldable<F>,
G: Foldable<G>
) =>
<B, A>(b: B, f: (b: B, a: A) => B) =>
<FS, FR, FO, FE, GS, GR, GO, GE>(
self: Kind<F, FS, FR, FO, FE, Kind<G, GS, GR, GO, GE, A>>
): B => pipe(self, F.reduceRight(b, (b, ga) => pipe(ga, G.reduceRight(b, f))))

/**
* @since 1.0.0
*/
export const toReadonlyArray = <F extends TypeLambda>(
Foldable: Foldable<F>
): <S, R, O, E, A>(self: Kind<F, S, R, O, E, A>) => ReadonlyArray<A> =>
toReadonlyArrayWith(Foldable)(identity)

/**
* @since 1.0.0
*/
export const toReadonlyArrayWith = <F extends TypeLambda>(
Foldable: Foldable<F>
) =>
<S, R, O, E, A, B>(self: Kind<F, S, R, O, E, A>, f: (a: A) => B): ReadonlyArray<B> =>
Foldable.reduce<A, Array<B>>([], (out, a) => {
out.push(f(a))
return out
})(self)
<A, B>(f: (a: A) => B) =>
<S, R, O, E>(self: Kind<F, S, R, O, E, A>): ReadonlyArray<B> =>
Foldable.reduce<A, Array<B>>([], (out, a) => {
out.push(f(a))
return out
})(self)

/**
* @since 1.0.0
Expand All @@ -40,4 +78,4 @@ export const foldMap = <F extends TypeLambda>(Foldable: Foldable<F>) =>
<M>(Monoid: Monoid<M>) =>
<A>(f: (a: A) => M) =>
<S, R, O, E>(self: Kind<F, S, R, O, E, A>): M =>
Monoid.combineAll(toReadonlyArrayWith(Foldable)(self, f))
Monoid.combineAll(toReadonlyArrayWith(Foldable)(f)(self))
60 changes: 54 additions & 6 deletions src/FoldableWithIndex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/

import type { Kind, TypeClass, TypeLambda } from "@fp-ts/core/HKT"
import { identity, pipe } from "@fp-ts/core/internal/Function"
import type { Monoid } from "@fp-ts/core/Monoid"

/**
Expand All @@ -21,17 +22,64 @@ export interface FoldableWithIndex<F extends TypeLambda, I> extends TypeClass<F>
) => <S, R, O, E>(self: Kind<F, S, R, O, E, A>) => B
}

/**
* Returns a default `reduceWithIndex` composition.
*
* @since 1.0.0
*/
export const reduceWithIndexComposition = <F extends TypeLambda, I, G extends TypeLambda, J>(
F: FoldableWithIndex<F, I>,
G: FoldableWithIndex<G, J>
) =>
<B, A>(b: B, f: (b: B, a: A, ij: readonly [I, J]) => B) =>
<FS, FR, FO, FE, GS, GR, GO, GE>(
self: Kind<F, FS, FR, FO, FE, Kind<G, GS, GR, GO, GE, A>>
): B =>
pipe(
self,
F.reduceWithIndex(b, (b, ga, i) =>
pipe(ga, G.reduceWithIndex(b, (b, a, j) => f(b, a, [i, j]))))
)

/**
* Returns a default `reduceRightWithIndex` composition.
*
* @since 1.0.0
*/
export const reduceRightWithIndexComposition = <F extends TypeLambda, I, G extends TypeLambda, J>(
F: FoldableWithIndex<F, I>,
G: FoldableWithIndex<G, J>
) =>
<B, A>(b: B, f: (b: B, a: A, ij: readonly [I, J]) => B) =>
<FS, FR, FO, FE, GS, GR, GO, GE>(
self: Kind<F, FS, FR, FO, FE, Kind<G, GS, GR, GO, GE, A>>
): B =>
pipe(
self,
F.reduceRightWithIndex(b, (b, ga, i) =>
pipe(ga, G.reduceRightWithIndex(b, (b, a, j) => f(b, a, [i, j]))))
)

/**
* @since 1.0.0
*/
export const toReadonlyArray = <F extends TypeLambda, I>(
FoldableWithIndex: FoldableWithIndex<F, I>
): <S, R, O, E, A>(self: Kind<F, S, R, O, E, A>) => ReadonlyArray<A> =>
toReadonlyArrayWith(FoldableWithIndex)(identity)

/**
* @since 1.0.0
*/
export const toReadonlyArrayWith = <F extends TypeLambda, I>(
FoldableWithIndex: FoldableWithIndex<F, I>
) =>
<S, R, O, E, A, B>(self: Kind<F, S, R, O, E, A>, f: (a: A, i: I) => B): ReadonlyArray<B> =>
FoldableWithIndex.reduceWithIndex<A, Array<B>>([], (out, a, i) => {
out.push(f(a, i))
return out
})(self)
<A, B>(f: (a: A, i: I) => B) =>
<S, R, O, E>(self: Kind<F, S, R, O, E, A>): ReadonlyArray<B> =>
FoldableWithIndex.reduceWithIndex<A, Array<B>>([], (out, a, i) => {
out.push(f(a, i))
return out
})(self)

/**
* @since 1.0.0
Expand All @@ -42,4 +90,4 @@ export const foldMapWithIndex = <F extends TypeLambda, I>(
<M>(Monoid: Monoid<M>) =>
<A>(f: (a: A, i: I) => M) =>
<S, R, O, E>(self: Kind<F, S, R, O, E, A>): M =>
Monoid.combineAll(toReadonlyArrayWith(FoldableWithIndex)(self, f))
Monoid.combineAll(toReadonlyArrayWith(FoldableWithIndex)(f)(self))
30 changes: 30 additions & 0 deletions src/FunctorWithIndex.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* @since 1.0.0
*/
import type { Kind, TypeClass, TypeLambda } from "@fp-ts/core/HKT"
import { pipe } from "@fp-ts/core/internal/Function"

/**
* @category type class
* @since 1.0.0
*/
export interface FunctorWithIndex<F extends TypeLambda, I> extends TypeClass<F> {
readonly mapWithIndex: <A, B>(
f: (a: A, i: I) => B
) => <S, R, O, E>(self: Kind<F, S, R, O, E, A>) => Kind<F, S, R, O, E, B>
}

/**
* Returns a default `mapWithIndex` composition.
*
* @since 1.0.0
*/
export const mapWithIndexComposition = <F extends TypeLambda, I, G extends TypeLambda, J>(
FunctorF: FunctorWithIndex<F, I>,
FunctorG: FunctorWithIndex<G, J>
): (<A, B>(
f: (a: A, ij: readonly [I, J]) => B
) => <FS, FR, FO, FE, GS, GR, GO, GE>(
self: Kind<F, FS, FR, FO, FE, Kind<G, GS, GR, GO, GE, A>>
) => Kind<F, FS, FR, FO, FE, Kind<G, GS, GR, GO, GE, B>>) =>
(f) => FunctorF.mapWithIndex((ga, i) => pipe(ga, FunctorG.mapWithIndex((a, j) => f(a, [i, j]))))
6 changes: 2 additions & 4 deletions src/Semigroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,13 @@ export const constant = <A>(a: A): Semigroup<A> => ({
* @since 1.0.0
*/
export const reverse = <A>(Semigroup: Semigroup<A>): Semigroup<A> => ({
combine: (that) => (self) => Semigroup.combine(that)(self),
combine: (that) => (self) => Semigroup.combine(self)(that),
combineMany: (collection) =>
(self) => {
const reversed = Array.from(collection).reverse()
return reversed.length === 0 ?
self :
Semigroup.combine(self)(
reversed.reduceRight((first, second) => Semigroup.combine(second)(first))
)
Semigroup.combine(self)(Semigroup.combineMany(reversed.slice(1))(reversed[0]))
}
})

Expand Down
11 changes: 0 additions & 11 deletions src/Semigroupal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,17 +93,6 @@ export const zip = <F extends TypeLambda>(Semigroupal: Semigroupal<F>) =>
): Kind<F, S, R1 & R2, O1 | O2, E1 | E2, readonly [A, B]> =>
pipe(self, Semigroupal.zipWith(that, (a, b) => [a, b]))

/**
* Zips this effect with the specified effect using the
* specified combiner function.
*
* @since 1.0.0
*/
export const zipWith = <F extends TypeLambda>(Semigroupal: Semigroupal<F>) =>
<S, R2, O2, E2, B, A, C>(that: Kind<F, S, R2, O2, E2, B>, f: (a: A, b: B) => C) =>
<R1, O1, E1>(self: Kind<F, S, R1, O1, E1, A>): Kind<F, S, R1 & R2, O1 | O2, E1 | E2, C> =>
pipe(self, Semigroupal.zipWith(that, f))

/**
* Returns an effect that executes both this effect and the specified effect,
* in parallel, this effect result returned. If either side fails, then the
Expand Down
6 changes: 6 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import * as flatMap from "@fp-ts/core/FlatMap"
import * as foldable from "@fp-ts/core/Foldable"
import * as foldableWithIndex from "@fp-ts/core/FoldableWithIndex"
import * as functor from "@fp-ts/core/Functor"
import * as functorWithIndex from "@fp-ts/core/FunctorWithIndex"
import * as hkt from "@fp-ts/core/HKT"
import * as invariant from "@fp-ts/core/Invariant"
import * as monad from "@fp-ts/core/Monad"
Expand Down Expand Up @@ -96,6 +97,11 @@ export {
* @since 1.0.0
*/
functor,
/**
* @category type classes
* @since 1.0.0
*/
functorWithIndex,
/**
* @since 1.0.0
*/
Expand Down
20 changes: 20 additions & 0 deletions test/Bounded.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as _ from "@fp-ts/core/Bounded"
import * as number from "./data/number"
import * as U from "./util"

describe("Bounded", () => {
it("clamp", () => {
const clamp = _.clamp(_.fromSortable<number>(number.Sortable, 1, 10))
U.deepStrictEqual(clamp(2), 2)
U.deepStrictEqual(clamp(10), 10)
U.deepStrictEqual(clamp(20), 10)
U.deepStrictEqual(clamp(1), 1)
U.deepStrictEqual(clamp(-10), 1)
})

it("reverse", () => {
const Bounded = _.reverse(_.fromSortable<number>(number.Sortable, 10, 1))
U.deepStrictEqual(Bounded.maximum, 1)
U.deepStrictEqual(Bounded.minimum, 10)
})
})
36 changes: 36 additions & 0 deletions test/FlatMap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as _ from "@fp-ts/core/FlatMap"
import { pipe } from "@fp-ts/core/internal/Function"
import * as O from "./data/Option"
import * as U from "./util"

describe("FlatMap", () => {
it("zipLeft", () => {
const zipLeft = _.zipLeft(O.FlatMap)
U.deepStrictEqual(pipe(O.none, zipLeft(O.none)), O.none)
U.deepStrictEqual(pipe(O.none, zipLeft(O.some(2))), O.none)
U.deepStrictEqual(pipe(O.some(1), zipLeft(O.none)), O.none)
U.deepStrictEqual(pipe(O.some(1), zipLeft(O.some(2))), O.some(1))
})

it("zipRight", () => {
const zipRight = _.zipRight(O.FlatMap)
U.deepStrictEqual(pipe(O.none, zipRight(O.none)), O.none)
U.deepStrictEqual(pipe(O.none, zipRight(O.some(2))), O.none)
U.deepStrictEqual(pipe(O.some(1), zipRight(O.none)), O.none)
U.deepStrictEqual(pipe(O.some(1), zipRight(O.some(2))), O.some(2))
})

it("bind", () => {
const bind = _.bind(O.FlatMap)
U.deepStrictEqual(pipe(O.Do, bind("a", () => O.none)), O.none)
U.deepStrictEqual(pipe(O.Do, bind("a", () => O.some(1))), O.some({ a: 1 }))
})

it("tap", () => {
const tap = _.tap(O.FlatMap)
U.deepStrictEqual(pipe(O.none, tap(() => O.none)), O.none)
U.deepStrictEqual(pipe(O.none, tap(() => O.some(2))), O.none)
U.deepStrictEqual(pipe(O.some(1), tap(() => O.none)), O.none)
U.deepStrictEqual(pipe(O.some(1), tap(() => O.some(2))), O.some(1))
})
})
Loading