Some examples
const f = <L, R>(xs: Either<L, R>[]): Either<L, R[]> => { throw new Error('Not Implemented') };
const f = <T>(xs: Promise<T>[]): Promise<T[]> => { throw new Error('Not Implemented') };
const f = <T>(xs: Box<T>[]): Box<T[]> => { throw new Error('Not Implemented') };
These all perform some sort of reducing. However, the semigroup here is just a List.
From a readability point of view, what would be some good names for such functions.
There is obviously some degree of subjectivity here, which is discouraged by SO. However, I feel it is also possible to say that a name is bad or good with some objective criteria/rationale.
maybe alone the line of collect
or gather
?
TypeScript isn't Haskell, but that's where I usually go to see if there's already a well-known name for the type of thing I'm creating.
Assuming that Either<L, T>
, Promise<T>
, and Box<T>
are all applicative functors over T
, then the function signatures <L,T>(x: Array<Either<L, T>>) => Either<L, Array<T>>
, <T>(x: Array<Promise<T>>) => Promise<Array<T>>
, and <T>(x: Array<Box<T>>) => Box<Array<T>>
would probably be called sequence
.
A sketch of the rules for what makes a type function F<T>
applicative functor over T
: you need to have some functions that act like this:
declare function pure<T>(x: T): F<T>;
declare function lift2<A, B, T>(cb: (a: A, b: B) => T): (fa: F<A>, fb: F<B>) => F<T>;
And then sequence
could be implemented like this:
function sequence<T>(x: Array<F<T>>): F<Array<T>> {
return x.reduce(lift2<T[], T, T[]>((xs, x) => xs.concat(x)), pure([]))
}
For Promise<T>
that's fairly straightforward:
function pure<T>(x: T): Promise<T> {
return Promise.resolve(x);
}
function lift2<A, B, T>(cb: (a: A, b: B) => T): (fa: Promise<A>, fb: Promise<B>) => Promise<T> {
return (fa: Promise<A>, fb: Promise<B>) => fa.then(a => fb.then(b => cb(a, b)))
}
and you could presumably come up with ones for Either<L, T>
and Box<T>
too.
Okay, hope that helps; good luck!