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

Sequence EitherT #79

Closed
OliverJAsh opened this issue May 14, 2017 · 2 comments
Closed

Sequence EitherT #79

OliverJAsh opened this issue May 14, 2017 · 2 comments

Comments

@OliverJAsh
Copy link
Collaborator

OliverJAsh commented May 14, 2017

I am trying to sequence an array of EitherT:

const allsuccess = [
    fp.either.right<string, number>(1),
    fp.either.right<string, number>(2),
    fp.either.right<string, number>(3),
]
    .map(fp.task.of)
    .map(task => new fp.eitherT.EitherT(fp.task, task));

sequence(fp.eitherT, array)(allsuccess).run();

However, I get this error:

src/main.ts(174,14): error TS2345: Argument of type 'typeof "/Users/OliverJAsh/Development/temp/fp-ts-test/node_modules/fp-ts/lib/EitherT"' is not assignable to parameter of type 'StaticApplicative<"EitherT">'.
  Types of property 'of' are incompatible.
    Type '<M extends "Array" | "Option" | "Either" | "Const" | "Dictionary" | "EitherT" | "Free" | "Identit...' is not assignable to type '<A>(a: A) => EitherT<any, any, A>'.
      Type '<L, A>(a: A) => EitherT<any, L, A>' is not assignable to type 'EitherT<any, any, any>'.
        Property 'monad' is missing in type '<L, A>(a: A) => EitherT<any, L, A>'.

Should this be possible?

For context, I have a bunch of tasks that I want to fire of in parallel, but as soon as one of them fails, I want to respond with that failure immediately—instead of waiting for the other tasks to finish and then sequencing the results.

This would be similar to Promise.all, which will return a rejected promise as soon as one of the promises is rejected.

@gcanti
Copy link
Owner

gcanti commented May 14, 2017

Should this be possible?

Yes but with some work: fp.eitherT is not a valid StaticApplicative (the first argument of sequence) because the exported fp.eitherT.of function has the wrong signature: https://github.com/gcanti/fp-ts/blob/master/src/EitherT.ts#L62. You must build a StaticApplicative dictionary specialized for task by yourself

import * as task from 'fp-ts/lib/Task'
import * as either from 'fp-ts/lib/Either'
import * as eitherT from 'fp-ts/lib/EitherT'
import * as array from 'fp-ts/lib/Array'
import * as traversable from 'fp-ts/lib/Traversable'

const allsuccess = [
  either.right<string, number>(1),
  either.right<string, number>(2),
  either.right<string, number>(3)
]
.map(task.of)
.map(t => new eitherT.EitherT(task, t))

const eitherTApplicative = {
  URI: eitherT.URI as eitherT.URI,
  of: eitherT.of(task),
  map<L, A, B>(f: (a: A) => B, fa: eitherT.EitherT<task.URI, L, A>) {
    return eitherT.map(f, fa)
  },
  ap<L, A, B>(fab: eitherT.EitherT<task.URI, L, (a: A) => B>, fa: eitherT.EitherT<task.URI, L, A>) {
    return eitherT.ap(fab, fa)
  }
}

const x: eitherT.EitherT<task.URI, string, number[]> = traversable.sequence(eitherTApplicative, array)(allsuccess)
x.value.run().then(y => console.log(y)) // Right([1,2,3])

Now writing eitherTApplicative is just boilerplate, I'll add a getStaticMonad to the EitherT module so you'll be able to simply write

const eitherTApplicative = eitherT.getStaticMonad(task)

@gcanti
Copy link
Owner

gcanti commented May 15, 2017

getStaticMonad will be available in the next release

@gcanti gcanti closed this as completed May 15, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants