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

How to aggregate all success/failures in list of Validation (sequence?) #71

Closed
OliverJAsh opened this Issue Feb 4, 2017 · 3 comments

Comments

Projects
None yet
3 participants
@OliverJAsh

OliverJAsh commented Feb 4, 2017

Hi, thanks for the fantastic library and learning resources.

I have Array<Validation<A, B>> and want to aggregate all the successes and failures, e.g. Array<Validation<A, B>> => Validation<Array<A>, Array<B>>.

I thought this was possible using control.monads.sequence, however I seem to get runtime error mr.chain is not a function, so I presume I must be doing something wrong.

I have had success sequencing a list of Eithers, but in my case I want to aggregate the left hand side as well, which from reading this blog post, it appears Validation should help.

Thanks!

@OliverJAsh

This comment has been minimized.

Show comment
Hide comment
@OliverJAsh

OliverJAsh Feb 4, 2017

Never mind, got it now!

// Array<Validation<A, B>> => Validation<Array<A>, Array<B>>
const sequenceValidations = validations => (
    validations
        .reduce((acc, validation) => (
            Validation.Success(a => b => a.concat(b)).ap(acc).ap(validation)
        ), Validation.of([]))
)

Is this function in the library anywhere?

OliverJAsh commented Feb 4, 2017

Never mind, got it now!

// Array<Validation<A, B>> => Validation<Array<A>, Array<B>>
const sequenceValidations = validations => (
    validations
        .reduce((acc, validation) => (
            Validation.Success(a => b => a.concat(b)).ap(acc).ap(validation)
        ), Validation.of([]))
)

Is this function in the library anywhere?

@robotlolita

This comment has been minimized.

Show comment
Hide comment
@robotlolita

robotlolita Feb 5, 2017

Member

@OliverJAsh Validations implement Applicative, rather than Monad, so sequence (which uses the Monad's interface .chain) doesn't work on them.

There isn't a function to aggregate Validations yet. Validations themselves already aggregate failures when you use .apply(), but the failure needs to have a .concat method. You can write a function to do this as:

const Validation = require('folktale/data/validation');
const curry = require('folktale/core/lambda/curry');

const intoArray = (x) => Array.isArray(x) ? x : [x];

const collect = (validations) =>
  validations.map(x => x.failureMap(intoArray)).reduce(
    (a, b) => a.ap(b),
    Validation.of(curry(validations.length, (...values) => values))
  );

So something like:

collect([a, b, c]);

Translates to:

Validation.of((a, b, c) => [a, b, c])
  .ap(a.failureMap(intoArray))
    .ap(b.failureMap(intoArray))
      .ap(c.failureMap(intoArray))
Member

robotlolita commented Feb 5, 2017

@OliverJAsh Validations implement Applicative, rather than Monad, so sequence (which uses the Monad's interface .chain) doesn't work on them.

There isn't a function to aggregate Validations yet. Validations themselves already aggregate failures when you use .apply(), but the failure needs to have a .concat method. You can write a function to do this as:

const Validation = require('folktale/data/validation');
const curry = require('folktale/core/lambda/curry');

const intoArray = (x) => Array.isArray(x) ? x : [x];

const collect = (validations) =>
  validations.map(x => x.failureMap(intoArray)).reduce(
    (a, b) => a.ap(b),
    Validation.of(curry(validations.length, (...values) => values))
  );

So something like:

collect([a, b, c]);

Translates to:

Validation.of((a, b, c) => [a, b, c])
  .ap(a.failureMap(intoArray))
    .ap(b.failureMap(intoArray))
      .ap(c.failureMap(intoArray))

@robotlolita robotlolita added this to the v2.0.0 milestone Feb 5, 2017

robotlolita added a commit that referenced this issue Mar 5, 2017

@robotlolita robotlolita self-assigned this Mar 5, 2017

robotlolita added a commit that referenced this issue Mar 5, 2017

@robotlolita robotlolita removed the in progress label Mar 5, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment