{"id":21858234,"url":"https://github.com/simpleart/pytyped-curry","last_synced_at":"2025-03-21T19:43:37.926Z","repository":{"id":65733459,"uuid":"598323684","full_name":"SimpleArt/pytyped-curry","owner":"SimpleArt","description":"Function currying that can be statically typed.","archived":false,"fork":false,"pushed_at":"2023-02-28T21:07:47.000Z","size":41,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-26T14:23:31.692Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SimpleArt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2023-02-06T21:40:11.000Z","updated_at":"2024-10-28T17:24:25.000Z","dependencies_parsed_at":"2023-02-19T15:30:58.351Z","dependency_job_id":null,"html_url":"https://github.com/SimpleArt/pytyped-curry","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimpleArt%2Fpytyped-curry","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimpleArt%2Fpytyped-curry/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimpleArt%2Fpytyped-curry/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimpleArt%2Fpytyped-curry/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SimpleArt","download_url":"https://codeload.github.com/SimpleArt/pytyped-curry/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244857833,"owners_count":20522095,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-28T02:44:26.468Z","updated_at":"2025-03-21T19:43:37.906Z","avatar_url":"https://github.com/SimpleArt.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pytyped-curry\n Function currying that can be statically typed.\n\nFunctional tool for currying a function. Currying a function makes\nthe function callable multiple times before the function is actually\nran. Use `curry(n)(func)` or `@curry(n)` to transform a function into\na curried function which takes `n` calls before running.\n\n## Imports\n\n```python\nfrom pytyped_curry import curry\nfrom pytyped_curry import decorator  # python \u003e= 3.9\n```\n\n## Example\n\n```python\n# Transform the function into a curried function that takes\n# two function calls before running.\n@curry(2)\ndef add(x: int, y: int) -\u003e int:\n    return x + y\n\n# Add needs to be called twice to be ran.\nadd(2)(3)  # 5\n\n# Partial evaluation is easy.\nincrement = add(1)\n\nincrement(5)  # 6\n\n# The two arguments accept multiple forms.\nadd(x=2)(y=3)\nadd(y=3)(x=2)\nadd(2, 3)()\nadd()(2, 3)\n```\n\n## For Decorators\n\nOften times writing decorators requires writing several nested functions.\nThis is often a hassle, and in many cases completely unnecessary due to\ncurrying.\n\nNote: `reveal_type` is ran using `mypy`.\n\n```python\nfrom typing import Callable, TypeVar\n\nT = typing.TypeVar(\"T\")\nRT = typing.TypeVar(\"RT\")\n\n@curry(2, ...)\ndef decorator(func: Callable[[T], RT], x: T) -\u003e RT:\n    print(\"Start\")\n    y = func(x)\n    print(\"Finished\")\n    return y\n\nreveal_type(decorator)\n\"\"\"\ndef (def (T`-1) -\u003e RT`-2) -\u003e def (T`-1) -\u003e RT`-2\n\"\"\"\n\n@decorator\ndef increment(x: int) -\u003e int:\n    return x + 1\n\nreveal_type(increment)\n\"\"\"\ndef (builtins.int) -\u003e builtins.int\n\"\"\"\n\n@curry(3, ...)\ndef rate_limit(timeout: float, func: Callable[[T], RT], x: T) -\u003e RT:\n    time.sleep(timeout)\n    return func(x)\n\nreveal_type(rate_limit)\n\"\"\"\ndef (builtins.float) -\u003e (def (T`-1) -\u003e RT`-2) -\u003e def (T`-1) -\u003e RT`-2\n\"\"\"\n\n@rate_limit(5)\ndef request_data(name: str) -\u003e int:\n    return len(name)\n\nreveal_type(request_data)\n\"\"\"\ndef (builtins.str) -\u003e builtins.int\n\"\"\"\n```\n\n## Documentation\n\n*New in Python 3.9*\n\nDoc-strings can be applied to arbitrary objects at runtime for runtime use\nwith the `help(...)` function. A few additional pieces of metadata are also\naccessible at runtime to provide clearer documentation, such as the name of\nthe result.\n\n```python\n@curry(3)\ndef add(x: int, y: int, z: int) -\u003e int:\n    \"\"\"Returns add(x)(y)(z) = x + y + z.\"\"\"\n    return x + y + z\n\nhelp(add)\n\"\"\"\nHelp on Curried in module __main__:\n\nadd = curry(3)(add(x: int, y: int, z: int) -\u003e int)\n    Returns add(x)(y)(z) = x + y + z.\n\n\"\"\"\"\n\nhelp(add(1))\n\"\"\"\nHelp on Curried in module __main__:\n\nadd(1) = curry(2)(add(x: int, y: int, z: int) -\u003e int, 1)\n    Returns add(x)(y)(z) -\u003e x + y + z.\n\n\"\"\"\n\nhelp(add(1)(2))\n\"\"\"\nHelp on Curried in module __main__:\n\nadd(1, 2) = curry(1)(add(x: int, y: int, z: int) -\u003e int, 1, 2)\n    Returns add(x)(y)(z) -\u003e x + y + z.\n\n\"\"\"\n\nadd(1)(2)(3)  # 6\n```\n\n## Type-Hinting\n\n*New in Python 3.8*\n\nType-hints for curried functions are nigh impossible in the general case, as\ncan be seen by the last example. However, this doesn't stop us from enabling\ntyping in many common use-cases. Curried functions are hinted as functions\nwhich take any arguments but take `n` calls, up to `n = 3` for Python \u003c\n(3, 11) and up to `n = 4` otherwise. Although the arguments are not\npreserved, the final return type is.\n\nNote: `reveal_type` is ran using `mypy`.\n\n```python\n@curry(2)\ndef add(x: int, y: int) -\u003e int:\n    return x + y\n\nreveal_type(add)\n\"\"\"\ndef (*Any, **Any) -\u003e def (*Any, **Any) -\u003e builtins.int\n\"\"\"\n```\n\nFor Python \u003c (3, 11), one can also use `curry(n, ...)` to hint the curried\nfunction as taking exactly `1` positional argument per call, up to `n = 3`.\n\n```python\n@curry(2, ...)\ndef add(x: int, y: int) -\u003e int:\n    return x + y\n\nreveal_type(add)\n\"\"\"\ndef (builtins.int) -\u003e def (builtins.int) -\u003e builtins.int\n\"\"\"\n```\n\nFor Python \u003e= (3, 11), one can also use `curry(n, ...)` to hint the curried\nfunction as taking exactly `1` positional argument per call, up to `n = 3`,\nexcept for the last call. Notice that the `y` parameter is preserved as a\npositional-or-keyword parameter.\n\n```python\n@curry(2, ...)\ndef add(x: int, y: int) -\u003e int:\n    return x + y\n\nreveal_type(add)\n\"\"\"\ndef (builtins.int) -\u003e def (y: builtins.int) -\u003e builtins.int\n\"\"\"\n```\n\nFor more precise hinting, one must use `typing.cast` around the currying\nfunction.\n\n```python\nfrom typing import Protocol, overload\n\n\nclass AddEmpty(Protocol):\n\n    def __call__(self) -\u003e int:\n        ...\n\n\nclass AddX(Protocol):\n\n    def __call__(self, x: int) -\u003e int:\n        ...\n\n\nclass AddY(Protocol):\n\n    def __call__(self, y: int) -\u003e int:\n        ...\n\n\nclass Add(Protocol):\n\n    @typing.overload\n    def __call__(self, x: int, y: int) -\u003e AddEmpty:\n        ...\n\n    @typing.overload\n    def __call__(self, x: int) -\u003e AddY:\n        ...\n\n    @typing.overload\n    def __call__(self, *, y: int) -\u003e AddX:\n        ...\n\n    def __call__(self, x, y):\n        ...\n\n\n@typing.cast(Add, curry(2))\ndef add(x: int, y: int) -\u003e int:\n    return x + y\n\nreveal_type(add)\n\"\"\"\n__main__.Add\n\"\"\"\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimpleart%2Fpytyped-curry","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimpleart%2Fpytyped-curry","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimpleart%2Fpytyped-curry/lists"}