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

Generic Point Free Function Returns Unexpected Type #1453

Open
jcsho opened this issue Jul 26, 2022 · 0 comments
Open

Generic Point Free Function Returns Unexpected Type #1453

jcsho opened this issue Jul 26, 2022 · 0 comments
Labels
bug Something isn't working

Comments

@jcsho
Copy link

jcsho commented Jul 26, 2022

Bug report

What's wrong

Trying to compose a generic function that converts between different container types fails to type check correctly when using generics. Hopefully I am just using this wrong.

Code:

from typing import Callable, TypeVar

from returns.io import IOResultE
from returns.pointfree import bind_result
from returns.result import ResultE
from typing_extensions import reveal_type

T1 = TypeVar("T1")
T2 = TypeVar("T2")
T3 = TypeVar("T3")
T4 = TypeVar("T4")


# this works correctly
def test(
    i: int,
    f1: Callable[[int], str],
    f2: Callable[[str], IOResultE[int]],
    f3: Callable[[int], ResultE[str]],
) -> IOResultE[str]:
    f1_res = f1(i)
    f2_res = f2(f1_res)
    f3_res = bind_result(f3)(f2_res)
    reveal_type(f3_res)
    return f3_res


# this passes typecheck with returns.io.IOResult[T3`-3, builtins.Exception]
def test_generic(
    i: T1,
    f1: Callable[[T1], IOResultE[T2]],
    f2: Callable[[T2], ResultE[T3]],
) -> IOResultE[T3]:
    f1_res = f1(i)
    f2_res = bind_result(f2)(f1_res)
    reveal_type(f2_res)
    return f2_res


# this fails typecheck with returns.io.IOResult[returns.io.IOResult[Any, Any], builtins.Exception]
def test_generic2(
    i: T1,
    f1: Callable[[T1], T2],
    f2: Callable[[T2], IOResultE[T3]],
    f3: Callable[[T3], ResultE[T4]],
) -> IOResultE[T4]:
    f1_res = f1(i)
    f2_res = f2(f1_res)
    f3_res = bind_result(f3)(f2_res)
    reveal_type(f3_res)
    return f3_res

Running mypy:

$ python3 -m mypy test.py
test.py:23: note: Revealed type is "returns.io.IOResult[builtins.str, builtins.Exception]"
test.py:34: note: Revealed type is "returns.io.IOResult[T3`-3, builtins.Exception]"
test.py:47: note: Revealed type is "returns.io.IOResult[returns.io.IOResult[Any, Any], builtins.Exception]"
test.py:48: error: Incompatible return value type (got "IOResult[IOResult[Any, Any], Exception]", expected "IOResult[T4, Exception]")
Found 1 error in 1 file (checked 1 source file)

How is that should be

I would have expected the return type for test_generic2 to be returns.io.IOResult[T4`-3, builtins.Exception]

System information

  • python version: 3.9.12

  • returns version: 0.19.0

  • mypy version: 0.95.0

  • hypothesis version (if any):

  • pytest version (if any):

@jcsho jcsho added the bug Something isn't working label Jul 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Development

No branches or pull requests

1 participant