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

Validation is deprecated, but it is not explained why #1569

Closed
adam-arold opened this issue Aug 27, 2021 · 15 comments
Closed

Validation is deprecated, but it is not explained why #1569

adam-arold opened this issue Aug 27, 2021 · 15 comments

Comments

@adam-arold
Copy link

📖 Documentation

I just looked at Validation in the modules list, but everything is crossed out and there is a comment at the end that I should use EitherT. There is no documentation about what EitherT does, or what the T stands for. It would be good if there was at least some information on these classes on how to use them, what they do, why is it deprecated, etc.

@raveclassic
Copy link
Collaborator

Well, let's be a bit more flexible here 🙂 We also don't have any goals for leaving consumers of this project on their own.

Documentation is hard and pretty often it is incomplete. This project is not an exception. We would like to invest more in documenting more at least the public API. Still, there's not much resource to do that as the project is OSS. In other words, we're always open for documentation PRs.

As for now, @adam-arold, feel free to check the Help section of the readme. The discord/slack channels there would be a better place to ask about things like EitherT (monad transformers) and others.

@adam-arold
Copy link
Author

@steida I don't see why asking about why something is deprecated and/or undocumented is related to learning FP. To be honest FP has a very steep learning curve and FP folks have a tendency to be arrogant about it. You seem to be one of those folks.

If you don't want others to use FP don't create an open source library. If you create one you also carry the burden of having to properly document it and sometimes to explain how these things work.

I know because I have an (unrelated) library of my own where people come on to my discord channel and ask about things.

The worst possible thing you can do that will also label you and all your work with a 🚩 is to give out answers like this.

@SRachamim
Copy link
Contributor

SRachamim commented Aug 27, 2021

What @steida says is not errogant. You surely agree that React doesn't need to explain HTML concepts. Also Tailwind doesn't need to explain CSS concepts and lodash assumes their consumers know JavaScript.

fp-ts didn't invent TypeScript or functional programming. Those two are the only two prerequisites to use the library.

It's not errogant, it's efficient. FP is a broad subject, and there are many ways to teach it. There are links to some resources on the web.

That being said, I still think documentation can improve in many aspects.

And yes, I think there should be an explanation for why it's deprecated with a link to an alternative.

@adam-arold
Copy link
Author

adam-arold commented Aug 27, 2021

I didn't say that @steida is arrogant. I said they seem like it, and there is a big difference. It doesn't matter if you're a paragon of humility if you don't look like one from the outside observer.

Also comparing FP to CSS and HTML is not a good comparison. Literally everybody knows HTML and CSS. It goes without saying. Knowing FP is not like that, and the inherent complexity of FP vs CSS is also an order of magnitude higher.

Take me for example: learning React for me was a breeze, learning Tailwind was a breeze too even though my CSS knowledge was outdated and I had to re-learn half of it. FP is a very different beast and it is hard to see this if you already know it.

Case in point: I still don't know why Validation is deprecated (what this issue is about) and what does it have to do with me knowing (or now knowing) FP. All I needed was something like "we deprecated it because of X, please use Y instead, here are the docs".

@SRachamim
Copy link
Contributor

Case in point: I still don't know why Validation is deprecated (what this issue is about) and what does it have to do with me knowing (or now knowing) FP. All I needed was something like "we deprecated it because of X, please use Y instead, here are the docs"

You are right. And I'm waiting for an answer just like you. :)

@xuanduc987
Copy link

xuanduc987 commented Aug 27, 2021

The alternative is calling either. getApplicativeValidation or taskeither.getApplicativeTaskValidation ... to get an applicative instance to used in apply.sequenceS or apply.sequenceT

The input of either. getApplicativeValidation is an instance of semigroup - to specify how two E could combine together into a new E.

If the you model the result of validation to be Either<E[], A> then it should be like this

declare validateName: (name: string) => either.Either<string[], string>
declare validateAge: (age: number) => either.Either<string[], number>

const Ap = either.getApplicativeValidation(array.getSemigroup<string>())

const person = apply.sequenceS({
  name: validateName('abc'),
  age: validateAge(10)
}) // => Either<string[], { name: string, age: number}>

@adam-arold
Copy link
Author

Thanks, @xuanduc987 ! What was the problem with Validation? Interestingly enough Arrow (FP library for Kotlin) also deprecated Validation a while ago. 💡

@xuanduc987
Copy link

And I agree that the document could be better.
Right now, user must now all the concept of fp and category theory before using this library.

@SRachamim
Copy link
Contributor

While Validation abstracts away many low-level details of a validation process, it's still too low-level solution compared to using a declarative codec.

@adam-arold
Copy link
Author

So it is deprecated because there is a better solution in io-ts?

@xuanduc987
Copy link

xuanduc987 commented Aug 27, 2021

I was not using fp-ts before v2 so this is just an educated guess based on git history.

  • pre v2, fp-ts use class-based data type. There was an Validation data type separated from Either
  • from v2, fp-ts changed to pure data type, push the use of pipe function. The Validation data type is no more, instead there was ValidationT (https://github.com/gcanti/fp-ts/blob/2.0.0/src/ValidationT.ts). ValidationT<M, E, A> is just M<Either<E, A>> with an Applicative instance knows how to combine E values.
  • In version 2.10 its functioning could be replicated with either.getApplicativeValidation and thus deprecated

@raveclassic
Copy link
Collaborator

@adam-arold

So it is deprecated because there is a better solution in io-ts?

It was deprecated because it's a special case of Either. The difference between Validation and Either is that during chain-ing or ap-ping (in other words, combining several things) Validation concats all errors in an instance of Semigroup (the simplest is Array) when Either "fails-fast" discarding the rest of the computation.
So the actual difference between them is the difference in the underlying Semigroup for errors.

@adam-arold
Copy link
Author

Thanks for the explanation, I'll close this.

@keobrien
Copy link

keobrien commented Aug 2, 2022

Still very new to FP, I'm sure there's a more efficient way to do this but this worked for me:

import { chain, match, left, right, Either } from "fp-ts/lib/Either";
import { pipe } from "fp-ts/lib/function";
import * as A from "fp-ts/lib/Array";

declare type Error = {
    key: string
}
declare type Errors = Array<Error>;
declare type Validation = Array<(a: any) => Either<Errors, any>>;

export const multipleValidations = (checks: Validation) => (input: any) => 
    pipe(
        checks,
        A.flap(input),
        A.lefts,
        A.flatten,
        result => result.length > 0 ? left(response(result)) : right(input)
    );

pipe(
    right(event),
    chain(multipleValidations([
        hasRequiredStringField('username'),
        hasRequiredStringField('password'),
        hasPasswordMinLength,
        _ => left([{ key: 'example' }])
    ])),
    match(
        (error) => error,
        _ => []
    )
)

@tonisives
Copy link

tonisives commented Feb 7, 2024

according to comments in source code, here is my solution:

  let Ap = TE.getApplicativeTaskValidation(T.ApplyPar,
    pipe(string.Semigroup, S.intercalate(", "))
  )

  let res = await pipe(
    sequenceT(Ap)(
      validateFileName(input.fileName),
      validateBucket(input.bucket),
    ),
    TE.mapLeft((it)=> Error(it)),
let validateFileName = (fileName?: string): TE.TaskEither<string, string> => {
  if (!fileName) return TE.left("fileName is required")
  if (!fileName.match(/.*(-all|-docs|)\.zip/))
    return TE.left("fileName not supported")
  return TE.right(fileName)
}

repo

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

6 participants