From fd275e4e90921290f9d3e1cba1fc7c0e6a0dd1fb Mon Sep 17 00:00:00 2001 From: hfutsora <346762712@qq.com> Date: Wed, 27 Jul 2022 11:25:51 +0800 Subject: [PATCH] feat(either): traverse --- src/Either.ts | 20 ++++++++++++++++---- src/Functors/Traversable.ts | 12 +++++++++--- test/Either.spec.ts | 8 ++++++-- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/Either.ts b/src/Either.ts index fecf3be..8a9e3cd 100644 --- a/src/Either.ts +++ b/src/Either.ts @@ -8,7 +8,7 @@ import { Alt2 } from './Functors/Alt' import { ChainRec2, tailRec } from './Functors/ChainRec' import { Comonad2 } from './Functors/Comonad' import { Extend2 } from './Functors/Extend' -import { Traversable2 } from './Functors/Traversable' +import { Traversable2, PipeableTraverse2 } from './Functors/Traversable' import { Applicative } from './Functors/Applicative' import { HKT } from './Functors/HKT' @@ -258,10 +258,22 @@ export const reduce = (f: (acc: B, a: A) => B, b: B) => (ma: Either n > 0 ? some(n): none) + * assert.deepStrictEqual(pipe(left('err'), f), some(left('err'))) + * assert.deepStrictEqual(pipe(right(1), f), some(right(1))) + * assert.deepStrictEqual(pipe(right(-1), f), none) + * ``` */ -export const traverse: (F: Applicative) => (f: (a: A) => HKT) => (e: Either) => HKT> = - F => f => e => isLeft(e) ? F.of(left(e.left)) : F.map(f(e.right), right) +export const traverse: PipeableTraverse2 = + (F: Applicative): (f: (a: A) => HKT) => (e: Either) => HKT> => + f => e => isLeft(e) ? F.of(left(e.left)) : F.map(f(e.right), right) /** * Returns `Either` if it's a `Right`, otherwise returns onLeft result. diff --git a/src/Functors/Traversable.ts b/src/Functors/Traversable.ts index 31160c6..f19fc31 100644 --- a/src/Functors/Traversable.ts +++ b/src/Functors/Traversable.ts @@ -13,7 +13,7 @@ import { HKT, KindOf, URIS } from './HKT' import { Functor, Functor1, Functor2 } from './Functor' import { Foldable, Foldable1, Foldable2 } from './Foldable' -import { Applicative, Applicative2 } from './Applicative' +import { Applicative, Applicative1, Applicative2 } from './Applicative' export interface Traversable extends Functor, Foldable { readonly traverse: (A: Applicative) => (ma: HKT, f: (a: A) => HKT) => HKT @@ -29,12 +29,18 @@ export interface Traversable2 extends Functor2, Foldable2 export interface Traverse { (F: Applicative2): (ma: KindOf, f: (a: A) => KindOf) => KindOf]> - (F: Applicative): (ma: KindOf, f: (a: A) => KindOf) => KindOf]> + (F: Applicative1): (ma: KindOf, f: (a: A) => KindOf) => KindOf]> (F: Applicative): (ma: KindOf, f: (a: A) => HKT) => HKT> } export interface Traverse2 { (F: Applicative2): (ma: KindOf, f: (a: A) => KindOf) => KindOf]> - (F: Applicative): (ma: KindOf, f: (a: A) => KindOf) => KindOf]> + (F: Applicative1): (ma: KindOf, f: (a: A) => KindOf) => KindOf]> (F: Applicative): (ma: KindOf, f: (a: A) => HKT) => HKT> } + +export interface PipeableTraverse2 { + (F: Applicative2): (f: (a: A) => KindOf) => (ta: KindOf) => KindOf]> + (F: Applicative1): (f: (a: A) => KindOf) => (ta: KindOf) => KindOf]> + (F: Applicative): (f: (a: A) => HKT) => (ta: KindOf) => HKT> +} diff --git a/test/Either.spec.ts b/test/Either.spec.ts index f8214bd..268e9f4 100644 --- a/test/Either.spec.ts +++ b/test/Either.spec.ts @@ -2,7 +2,8 @@ import { isLeft, left, right, isRight, map, of, fromPredicate, match, getOrElse, chain, orElse, exists, alt, getLeft, getRight, fromMaybe, tryCatch, swap, equals, ap, chainRec, extend, extract, reduce, traverse, filterOrElse } from '../src/Either' import { flow, pipe } from '../src/Pipe' -import { none, some } from '../src/Maybe' +import { none, some, Monad as MM } from '../src/Maybe' + test('isLeft', () => { expect(isLeft(left(0))).toBeTruthy() @@ -130,7 +131,10 @@ test('reduce', () => { }) test('traverse', () => { - // TODO: + const f = traverse(MM)((n: number) => n > 0 ? some(n): none) + expect(pipe(left('err'), f)).toEqual(some(left('err'))) + expect(pipe(right(1), f)).toEqual(some(right(1))) + expect(pipe(right(-1), f)).toEqual(none) }) test('orElse', () => {