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

Convert Either to Validation #76

Closed
OliverJAsh opened this issue May 13, 2017 · 5 comments
Closed

Convert Either to Validation #76

OliverJAsh opened this issue May 13, 2017 · 5 comments

Comments

@OliverJAsh
Copy link
Collaborator

Is it possible to write a function that converts an Either to a Validation?

I presume this would only work if the Left type was a semigroup, as that is required by Validation?

Here was my attempt, however it fails to compile:

import { StaticSemigroup } from "fp-ts/lib/Semigroup";

const eitherToValidation = <L, A>(
    either: either.Either<StaticSemigroup<L>, A>,
): validation.Validation<L, A> => {
    return either
        .fold(
            leftSemigroup => (
                validation.failure<L, A>([], leftSemigroup)
            ),
            right => validation.success<L, A>(right),
        );
};
@OliverJAsh
Copy link
Collaborator Author

OliverJAsh commented May 13, 2017

For context, I am using io-ts which returns an Either type, but I have a function that needs to return Validation.

I'd also be curious to know why io-ts uses Either and not Validation? :-)

@sledorze
Copy link
Collaborator

sledorze commented May 13, 2017

@OliverJAsh
Try something like that (not tested)

const eitherToValidation = <L, A>(
  leftSemigroup: StaticSemigroup<L>,
  either: either.Either<L, A>,
): validation.Validation<L, A> =>
  either.fold(
    left => validation.failure<L, A>(leftSemigroup, left),
    right => validation.success<L, A>(right),
  )

Usage (with array):

eitherToValidation(array, either.left([10]))

@sledorze
Copy link
Collaborator

@OliverJAsh
You may use that one, it's more specific (force the usage of array) but may be handy.

const eitherToValidation = <L,A>(
  either: either.Either<L, A>,
): validation.Validation<L[], A> =>
  either.fold(
    left => validation.failure<L[], A>(array, [left]),
    right => validation.success<L[], A>(right),
  )

Usage

eitherToValidation(either.left(10))

@gcanti
Copy link
Owner

gcanti commented May 14, 2017

I'd also be curious to know why io-ts uses Either and not Validation?

That's a good question!

Either, having a monad instance, is strictly more powerful than Validation. You lose the ability to run validations in parallel but you gain the chainability of validations. There are many validations which can't be parallelized, for example integers

  • first you must check that the input is a number
  • then you must check that the number is an integer

That "then" requires the power of a monad and its chain function

import { left, right } from 'fp-ts/lib/Either'

// any -> number
const isNumber = (input: any) => typeof input === 'number' ? right<string, number>(input) : left<string, number>('Not a number')

// number -> integer
const isNumberInteger = (input: number) => input % 1 === 0 ? right<string, number>(input) : left<string, number>('Not an integer')

// now I can compose the validations

// any -> integer
const isInteger = (input: any) => isNumber(input).chain(isNumberInteger)

console.log(isInteger('s')) // Left("Not a number")
console.log(isInteger(1.1)) // Left("Not an integer")
console.log(isInteger(1)) // Right(1)

I used the term "compose" because monads are a way to make composable a group of functions which naturally don't compose. Those functions, called Kleisli arrows, have the following general signature

A -> M<B>
b -> M<C>

where M is a type constructor (kind * -> *). In case of Either we get (its left type is not important for what we are saying)

any -> Either<number>
number -> Either<integer>

From this point of view monads are pretty easy to explain: under the hood is just function composition (well to be precise is morphism composition).

This is a repo where I try to explain all these things (I put up a functional programming meet up here in Milano and the repo contains a series of lectures I gave during the last months)

Alas is in italian..

https://github.com/gcanti/functional-programming

@OliverJAsh
Copy link
Collaborator Author

Super useful and insightful replies. Thank you! :-)

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

3 participants