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),
);
};
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? :-)
@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]))
@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))
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
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..
Super useful and insightful replies. Thank you! :-)
Most helpful comment
That's a good question!
Either, having a monad instance, is strictly more powerful thanValidation. 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 integersThat "then" requires the power of a monad and its
chainfunctionI 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
where
Mis a type constructor (kind* -> *). In case ofEitherwe get (its left type is not important for what we are saying)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