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

Add tapNoneIO for Option, TaskOption and IOOption and tapErrorIO for Either, TaskEither and IOEither #1915

Open
iFreilicht opened this issue Nov 21, 2023 · 0 comments

Comments

@iFreilicht
Copy link

🚀 Feature request

Current Behavior

Right now, if I want to log that a function has returned none, there's no tapNone function, I have to do a dance with altW:

   O.altW(() => {
      console.log('My important thing failed!');
      return O.none;
    }),

For Either, tapError requires a similar dance, though for a different reason. It's signature requires a function that returns the same monad, even though the value in that monad isn't used.

  TE.tapError((e) => {
    console.log(`An error occurred: ${e}`);
    return e;  // I could return anything here, as long as it's still a TaskEither. But I can't return nothing
  }

Desired Behavior

I would like to be able to do write code like this

   O.tapXYZ(() => {
      console.log('My important thing failed!')
    }),
  TE.tapXYZ((e) => {
    console.log(`An error occurred: ${e}`);
  }

Suggested Solution

To stay consistent, it seems these should be IO functions. tapNone wouldn't make a lot of sense with the Option-based types (you literally have no input and no output). but tapNoneIO would, and it would allow writing code like this:

   O.tapNoneIO(() => () => {
      console.log('My important thing failed!')
    }),

Similarly, for Either-based types, tapErrorIO would work:

  TE.tapErrorIO((e) => () => {
    console.log(`An error occurred: ${e}`);
  }

It's not perfect, you still need to pass a higher order function, which feels somewhat unnecessary, but it is consistent with tapIO and makes sense in the overall ecosystem.

Who does this impact? Who is this for?

Anyone who wants to perform side-effects on none and left with minimal boilerplate. It is only a quality-of-life improvement, there is no new functionality here.

Describe alternatives you've considered

  • A new class of functions that doesn't require the additional indirection. This seems like way more effort, and I'm not sure if it's even possible to integrate into fp-ts' execution model
  • Not adding these functions. Would be ok as well, I'm not blocked by this, but it feels inconsistent.

Your environment

Software Version(s)
fp-ts 2.16.1
TypeScript 5.1.6
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

1 participant