{"action":"created","issue":{"url":"https://api.github.com/repos/python/mypy/issues/3062","repository_url":"https://api.github.com/repos/python/mypy","labels_url":"https://api.github.com/repos/python/mypy/issues/3062/labels{/name}","comments_url":"https://api.github.com/repos/python/mypy/issues/3062/comments","events_url":"https://api.github.com/repos/python/mypy/issues/3062/events","html_url":"https://github.com/python/mypy/issues/3062","id":217298527,"number":3062,"title":"Simple dependent types","user":{"login":"JukkaL","id":1107911,"avatar_url":"https://avatars1.githubusercontent.com/u/1107911?v=3","gravatar_id":"","url":"https://api.github.com/users/JukkaL","html_url":"https://github.com/JukkaL","followers_url":"https://api.github.com/users/JukkaL/followers","following_url":"https://api.github.com/users/JukkaL/following{/other_user}","gists_url":"https://api.github.com/users/JukkaL/gists{/gist_id}","starred_url":"https://api.github.com/users/JukkaL/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JukkaL/subscriptions","organizations_url":"https://api.github.com/users/JukkaL/orgs","repos_url":"https://api.github.com/users/JukkaL/repos","events_url":"https://api.github.com/users/JukkaL/events{/privacy}","received_events_url":"https://api.github.com/users/JukkaL/received_events","type":"User","site_admin":false},"labels":[{"id":46131301,"url":"https://api.github.com/repos/python/mypy/labels/needs%20discussion","name":"needs discussion","color":"bfdadc","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":20,"created_at":"2017-03-27T16:15:38Z","updated_at":"2017-04-17T06:04:10Z","closed_at":null,"body":"[This is based on a discussion between me and @gvanrossum last week. I'm writing this down so that we won't forget about this.]\r\n\r\nSeveral stdlib functions have signatures where the return type depends on the value of an argument. Examples:\r\n\r\n* `open` returns an `IO[str]` or `IO[bytes]` depending on whether the mode argument has `'b'` as a substring.\r\n* `subprocess.check_output` returns a `str` or `bytes` depending on the value of the boolean `universal_newlines` argument.\r\n\r\nA simple way to support these would be to introduce a few additional types that work with `str` and `bool` literals:\r\n\r\n* A string pattern type that can describe the contents of a string literal, perhaps using a regular expression.\r\n* Types for `False` and `True`.\r\n\r\nFor example, if we had `FalseType` and `TrueType`, we could write a function whose return value depends on the value of a boolean argument:\r\n\r\n```py\r\n@overload\r\ndef f(x: FalseType) -> bytes: ...\r\n@overload\r\ndef f(x: TrueType) -> str: ...\r\n\r\ndef f(x: Any) -> Any:\r\n    if x:\r\n        return 'x'\r\n    else:\r\n        return b'x'\r\n\r\nreveal_type(f(False))  # bytes\r\nreveal_type(f(True)  # str\r\n```\r\n\r\nNot sure about this one:\r\n\r\n```py\r\n...\r\nx = bool('')\r\nreveal_type(f(x))  # Union[str, bytes] since we don't know the boolean value statically?\r\n```\r\n\r\nWe could also have a generic class where a generic type argument depends on the value of an argument to `__init__`. Not sure how we should represent these -- here is one potential approach:\r\n\r\n```py\r\nclass C(Generic[AnyStr]):\r\n    @overload\r\n    @returntype('C[str]')\r\n    def __init__(self, x: TrueType) -> None: ...\r\n    @overload\r\n    @returntype('C[bytes]')\r\n    def __init__(self, x: FalseType) -> None: ...\r\n    ...\r\n\r\nreveal_type(C(True))  # C[str]\r\n```\r\n\r\nAlternatively, we could use `__new__`, but this would be problematic if there is no corresponding method defined at runtime."},"comment":{"url":"https://api.github.com/repos/python/mypy/issues/comments/294412284","html_url":"https://github.com/python/mypy/issues/3062#issuecomment-294412284","issue_url":"https://api.github.com/repos/python/mypy/issues/3062","id":294412284,"user":{"login":"pkch","id":1593648,"avatar_url":"https://avatars1.githubusercontent.com/u/1593648?v=3","gravatar_id":"","url":"https://api.github.com/users/pkch","html_url":"https://github.com/pkch","followers_url":"https://api.github.com/users/pkch/followers","following_url":"https://api.github.com/users/pkch/following{/other_user}","gists_url":"https://api.github.com/users/pkch/gists{/gist_id}","starred_url":"https://api.github.com/users/pkch/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pkch/subscriptions","organizations_url":"https://api.github.com/users/pkch/orgs","repos_url":"https://api.github.com/users/pkch/repos","events_url":"https://api.github.com/users/pkch/events{/privacy}","received_events_url":"https://api.github.com/users/pkch/received_events","type":"User","site_admin":false},"created_at":"2017-04-17T06:04:10Z","updated_at":"2017-04-17T06:04:10Z","body":"TypeScript 2.0 (Oct 2016) added precisely these [simple (literal) dependent types](https://basarat.gitbooks.io/typescript/docs/types/literal-types.html). Their stated use cases are enum, dealing with legacy APIs, and as a [tag for a Union](https://basarat.gitbooks.io/typescript/docs/types/discriminated-unions.html); all somewhat relevant.\r\n\r\nJust thought I'd point this out since they seem to be solving a similar problem to what is being discussed here."}}
{"actor":{"display_login":"pkch"}}