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

Left and Right don't unify #128

Closed
DylanRJohnston opened this issue Jun 15, 2017 · 7 comments
Closed

Left and Right don't unify #128

DylanRJohnston opened this issue Jun 15, 2017 · 7 comments

Comments

@DylanRJohnston
Copy link

import {Either, Left, Right} from 'fp-ts/lib/either'

const foo = (x: number) => x < 5 ? Right.of(x) : Left.of("Not less than 5")
const bar = (x: number) => x > 2 ? Right.of(x) : Left.of("Not greater than 2")

Inferred type of foo

const foo: (x: number) => Left<{}, number> | Right<{}, number> | Left<{}, string> | Right<{}, string>

Trying to add return type

const foo = (x: number): Either<string, number> => x < 5 ? Right.of(x) : Left.of("Not less than 5")

Produces the error

[ts]
Type 'Left<string, number> | Right<string, number> | Left<string, string> | Right<string, string>' is not assignable to type 'Either<string, number>'.
  Type 'Left<string, string>' is not assignable to type 'Either<string, number>'.
    Type 'Left<string, string>' is not assignable to type 'Left<string, number>'.
      Type 'string' is not assignable to type 'number'.

This happens in both 2.3.4 and 2.4.0. But given improvements in the type checker in 2.4.0 I thought there may be a way to potentially fix. Not sure where to get started though.

Relevant changes to the typechecker in 2.4.0
microsoft/TypeScript#16072
microsoft/TypeScript#16305
microsoft/TypeScript#16368

@DylanRJohnston
Copy link
Author

Actually I looked closer at the definition of Left.of and it doesn't do what I thought it did.

In any case, replacing if with left and right still does't solve the problem.

import {Either, right as Right, left as Left} from 'fp-ts/lib/either'

const foo = (x: number): Either<number, string> => x < 5 ? Right(x) : Left("Not less than 5")
const bar = (x: number): Either<number, string> => x > 2 ? Right(x) : Left("Not greater than 2")
[ts]
Type 'Left<number, number> | Right<number, number> | Left<string, string> | Right<string, string>' is not assignable to type 'Either<number, string>'.
  Type 'Left<number, number>' is not assignable to type 'Either<number, string>'.
    Type 'Left<number, number>' is not assignable to type 'Left<number, string>'.
      Type 'number' is not assignable to type 'string'.

@DylanRJohnston
Copy link
Author

DylanRJohnston commented Jun 15, 2017

This works though (in 2.4.0 not 2.3.4)

function foobar(x: number): Either<string, number> {
    if (x < 5) {
        return Right(x);
    } else {
        return Left('FooBar');
    }
}

Maybe it's just ternary statements?

@DylanRJohnston
Copy link
Author

Actually this works too. So maybe its just arrow functions

function foobar(x: number): Either<string, number> {
    return x < 5 ? Right(x) : Left("fooBar")
}

@DylanRJohnston
Copy link
Author

I'll close this as it seems an upstream issue

@DylanRJohnston
Copy link
Author

Nevermind, I had the types backwards on the Either in the arrow functions. Whoops.

@gcanti
Copy link
Owner

gcanti commented Jun 15, 2017

Left.of is not a constructor for Left, is the of function of Applicative

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

// Right.of = Left.of = right = of <= all functions are the same: return a Right

You should use left, right (lowercase) or new Left(...), new Right(...)

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

// typescript v2.3.4...
const foo = (x: number) => (x < 5 ? right<string, number>(x) : left<string, number>('Not less than 5'))
const bar = (x: number) => (x > 2 ? right<string, number>(x) : left<string, number>('Not greater than 2'))

// ...or typescript v2.4.0
const foo = (x: number): Either<string, number> => (x < 5 ? right(x) : left('Not less than 5'))
const bar = (x: number): Either<string, number> => (x > 2 ? right(x) : left('Not greater than 2'))

@DylanRJohnston
Copy link
Author

Yeah thanks, I realised my mistake after looking at the definition, makes sense.

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