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

0.4.0 TaskEither issues #152

Closed
OliverJAsh opened this issue Jul 14, 2017 · 5 comments
Closed

0.4.0 TaskEither issues #152

OliverJAsh opened this issue Jul 14, 2017 · 5 comments

Comments

@OliverJAsh
Copy link
Collaborator

Hey @gcanti, I'm upgrading to fp-ts 0.4.0 and I ran into this issue with TaskEither. See the error in the code.

Do you have any ideas what's going on here?

import * as apply from 'fp-ts/lib/Apply';
import * as tuple from 'fp-ts/lib/Tuple';
import { Task } from 'fp-ts/lib/Task';

import * as taskEither from './TaskEither';

import Tuple = tuple.Tuple;
import TaskEither = taskEither.TaskEither;

// tuple constructor
const toTuple2 = <A, B>(a: A, b: B): tuple.Tuple<A, B> => new tuple.Tuple([ a, b ]);

// lifted tuple constructor
const taskEitherToTuple2 = <L, A, B>(fa: TaskEither<L, A>, fb: TaskEither<L, B>) =>
    apply.liftA2(taskEither, (a: A) => (b: B) => toTuple2(a, b))(fa, fb);

type Tuple2TaskEither<L, A, B> = (tuple.Tuple<TaskEither<L, A>, TaskEither<L, B>>);

export const toTaskEitherTuple2 = <L, A, B>(t: Tuple2TaskEither<L, A, B>) =>
    taskEitherToTuple2(t.fst(), t.snd());

const taskEither1: TaskEither<number, number> = taskEither.of(1)
const taskEither2: TaskEither<number, number> = taskEither.of(2)
toTaskEitherTuple2(new Tuple([taskEither1, taskEither2]))
    // Error: [ts] Property 'chain' does not exist on type 'HKT<"TaskEither", Tuple<number, number>>'.
    .chain(tupleInstance => {

    })
@gcanti
Copy link
Owner

gcanti commented Jul 14, 2017

How is defined your TaskEither?

@OliverJAsh
Copy link
Collaborator Author

@gcanti
Copy link
Owner

gcanti commented Jul 14, 2017

Ok so, this fp-ts version is necessarily less smart than the previous one when it comes to transform a HKT<F, A> into a concrete type, it needs some hints through a list of "overloadings".

In this case liftA2 returns correctly HKT<"TaskEither", Tuple<number, number>> but while we, as developers, know that is equivalent to TaskEither<number, Tuple<number, number>> the compiler can't know that, so we need to add an hint

// add this to the `TaskEither` file

import { Curried2 } from 'fp-ts/lib/function'

declare module 'fp-ts/lib/Apply' {
  interface Ops {
    liftA2<A, B, C>(
      apply: Apply<URI>, // <= important: this is the URI of TaskEither
      f: Curried2<A, B, C>
    ): <L>(fa: TaskEither<L, A>, fb: TaskEither<L, B>) => TaskEither<L, C>
  }
}

In practice by doing that we provide a proof to the compiler that it can trasform a HKT<'TaskEither', A> into a TaskEither<L, A> in the context of liftA2. Does it make sense?

@OliverJAsh
Copy link
Collaborator Author

@gcanti Amazing, thank you. Good to understand why that is necessary.

Can we add this to the example TaskEither in this repo? I will try to write some documentation once I understand things a bit better.

@gcanti
Copy link
Owner

gcanti commented Jul 14, 2017

btw this is the reason why you can find a file named overloadings.ts in the lib folder which contains a big list of built-in overloadings written by me (PRs welcomed)

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

2 participants