{ "info": { "author": "Correl Roush", "author_email": "correl@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 2 - Pre-Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3 :: Only", "Topic :: Software Development :: Libraries" ], "description": "# Type-safe Monads\n\n[![Build Status](https://travis-ci.com/correl/typesafe-monads.svg?branch=master)](https://travis-ci.com/correl/typesafe-monads)\n[![codecov](https://codecov.io/gh/correl/typesafe-monads/branch/master/graph/badge.svg)](https://codecov.io/gh/correl/typesafe-monads)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)\n\nThis is an experiment in building monads in Python supported by strict\ntype annotations. The goal is to be able to compose monads with the\ntype checker ensuring their correctness.\n\n\n## Motivation\n\nI'm a fan of monads, but believe they work best with the support of a\nstrong type system. I've attempted to use libraries like\n[PyMonad](https://pypi.org/project/PyMonad/), but been frustrated by a\nlack of type constraints preventing incorrect usage. I could've\nattempted to add type annotations to one of those libraries, but\nbuilding my own is more fun.\n\n\n## Base Classes\n\n### Functor\n\n#### map (`*`)\n\nApplies a function to the contents of a functor, transforming it from\none thing to another.\n\nThe `*` operator implements map on functors, and is both left and\nright associative:\n\n```python\ndef wordcount(s: str):\n return len(s.split())\n\n\nf.map(wordcount) == wordcount * f == f * wordcount\n```\n\n### Applicative\n\n*Extends `Functor`.*\n\n#### pure\n\nWraps a value in an applicative functor.\n\ne.g.:\n\n Maybe.pure(\"abc\") == Just(\"abc\")\n Result.pure(123) == Ok(123)\n\n#### apply (`&`)\n\nTransforms the value contained in the instance's functor with a\nfunction wrapped in the same type of functor.\n\nThe `&` operator implements apply on applicatives, and is\nright-associative.\n\ne.g.:\n\n```python\nincrement = lambda x: x + 1\n\nJust(3).apply(Just(increment)) == Just(increment) & Just(3) == Just(4)\n```\n\nThis can be very handily combined with map to apply curried functions\nto multiple arguments:\n\n```python\nsubtract = lambda x: lambda y: x - y\n\nsubtract * Just(10) & Just(4) == Just(6)\n```\n\n### Monad\n\n*Extends `Applicative`.*\n\n#### bind (`>>`)\n\nPasses the value within the monad through an operation returning the\nsame type of monad, allowing multiple operations to be chained.\n\nThe `>>` operator implements bind on monads, and is left-associative.\n\n```python\n@curry\ndef lookup(key: str, dictionary: Dict[str, str]) -> Maybe[str]:\n try:\n return Just(dictionary[key])\n except KeyError:\n return Nothing()\n\n\nresult = Just({\"hello\": \"world\"}).bind(lookup(\"hello\")).bind(lambda s: s.upper())\nresult = (\n Just({\"hello\": \"world\"})\n >> lookup(\"hello\")\n >> (lambda s: s.upper())\n)\n```\n\n### Monoid\n\n#### mappend (`+`)\n\nDescribes an associative binary operation for a type.\n\n#### mzero\n\nProvides an identity value for the `mappend` operation.\n\n#### mconcat\n\nAccumulates a list of values using `mappend`. Returns the `mzero`\nvalue if the list is empty.\n\n## Monads\n\n### Maybe[T]\n\nRepresents optional data. A `Maybe` instance of a certain type `T` will\neither be a `Just` object wrapping a value of that type, or `Nothing`.\n\n- Mapping a function over `Nothing` will return `Nothing` without\n calling the function.\n- Binding an operation with a `Nothing` will return `Nothing` without\n attempting the operation.\n\n### Result[T, E]\n\nRepresents a state of success or failure, declaring a type for each. A\n`Result` instance will either be an `Ok` object wrapping a value of\nthe success type `T`, or an `Err` object wrapping a value of the\nfailure type `E`.\n\n- Mapping a function over an `Err` will return the `Err` unchanged\n without calling the function.\n- Binding an operation with an `Err` will return the `Err` unchanged\n without attempting the operation.\n\n### List[T]\n\nRepresents a sequence of items.\n\n- Also implements `Monoid`.\n\n### Future[T]\n\nRepresents an asynchronous action.\n\n- Also implements `Awaitable`.\n\n### Reader[T]\n\nRepresents the application of a function to it's argument.\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/correl/typesafe-monads", "keywords": "", "license": "", "maintainer": "", "maintainer_email": "", "name": "typesafe-monads", "package_url": "https://pypi.org/project/typesafe-monads/", "platform": "", "project_url": "https://pypi.org/project/typesafe-monads/", "project_urls": { "Homepage": "https://github.com/correl/typesafe-monads" }, "release_url": "https://pypi.org/project/typesafe-monads/0.8/", "requires_dist": null, "requires_python": "", "summary": "Type-annotated monad implementations for Python 3.7+", "version": "0.8" }, "last_serial": 5387223, "releases": { "0.2": [ { "comment_text": "", "digests": { "md5": "05ec77e6214f4675446286a045ef4cd8", "sha256": "ee3b1c1829a03fd31dbe32068068af18821621f6b471269081afa3106d41fbc7" }, "downloads": -1, "filename": "typesafe_monads-0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "05ec77e6214f4675446286a045ef4cd8", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 8007, "upload_time": "2018-11-29T19:06:10", "url": "https://files.pythonhosted.org/packages/38/54/3157e9af0b0967feeb3dc1da6ec821bbb8523263f8a6568d74f3d35d484e/typesafe_monads-0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "54dcf830750c43df38cfad4633dbebe6", "sha256": "9c73966264306813bbc60c7c9bf8ede9e0ac3d51fc9b660ca7d066227234cf76" }, "downloads": -1, "filename": "typesafe-monads-0.2.tar.gz", "has_sig": false, "md5_digest": "54dcf830750c43df38cfad4633dbebe6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4138, "upload_time": "2018-11-29T19:06:12", "url": "https://files.pythonhosted.org/packages/2b/48/dcc1fec6b0c70ed7bdb324e6844d11c15b64168251b87c77c61152365538/typesafe-monads-0.2.tar.gz" } ], "0.3": [ { "comment_text": "", "digests": { "md5": "e4f0e8f7344c2bedb9fcf8fee05f856a", "sha256": "8974b279b14c1ce0fefd3b636fc75a0be1a142fae1602d14630cd49e0306cf2f" }, "downloads": -1, "filename": "typesafe_monads-0.3-py3-none-any.whl", "has_sig": false, "md5_digest": "e4f0e8f7344c2bedb9fcf8fee05f856a", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 8280, "upload_time": "2018-12-03T21:22:04", "url": "https://files.pythonhosted.org/packages/44/9a/4dfab4b6a39267f33a509572282def54f2f715506ca65bb32751e5965d74/typesafe_monads-0.3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "de534c92134724ca0767dab61a51c60d", "sha256": "7d4a16e2f7c1b1be5113de31b48bf0f64103d81d3dfa5e0f0fcbfa4b878c8b2c" }, "downloads": -1, "filename": "typesafe-monads-0.3.tar.gz", "has_sig": false, "md5_digest": "de534c92134724ca0767dab61a51c60d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4260, "upload_time": "2018-12-03T21:22:05", "url": "https://files.pythonhosted.org/packages/b1/06/cb57cbccd4cbd1130aa210b1161b806d504f73cd74c3e5573a7be53a2217/typesafe-monads-0.3.tar.gz" } ], "0.4": [ { "comment_text": "", "digests": { "md5": "6c169ea6ec2d6f6d445e290d83af2142", "sha256": "bdb02b44d02700267e8e91ebea0e1a7eef5a2d66784509a00829575930f5937c" }, "downloads": -1, "filename": "typesafe_monads-0.4-py3-none-any.whl", "has_sig": false, "md5_digest": "6c169ea6ec2d6f6d445e290d83af2142", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 8485, "upload_time": "2018-12-06T19:02:49", "url": "https://files.pythonhosted.org/packages/b6/d7/3d5154501769c2ce8f7cc9c66b5d86f0bf398e0c550d1eb4129b453fcf77/typesafe_monads-0.4-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "cd3884e74ae0c80d39d5246737a838da", "sha256": "8e7aaa58d3d409de68227201206cf073a7f012b17f556a4ff007fe89272fbf2a" }, "downloads": -1, "filename": "typesafe-monads-0.4.tar.gz", "has_sig": false, "md5_digest": "cd3884e74ae0c80d39d5246737a838da", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4360, "upload_time": "2018-12-06T19:02:51", "url": "https://files.pythonhosted.org/packages/c7/36/1f7e71c039a9a009e9d7a4386bb906498da8fd19f0c85207ae542d29ad0d/typesafe-monads-0.4.tar.gz" } ], "0.5": [ { "comment_text": "", "digests": { "md5": "5ee8d6c25f52dbf28236daff8f60ea3e", "sha256": "f81cf0112cbe66a56548fc0426a18fbd0b90d36b0258fb8d25035582b77f9eaa" }, "downloads": -1, "filename": "typesafe_monads-0.5-py3-none-any.whl", "has_sig": false, "md5_digest": "5ee8d6c25f52dbf28236daff8f60ea3e", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 9975, "upload_time": "2018-12-12T06:56:53", "url": "https://files.pythonhosted.org/packages/ef/cc/187195322aa7f5f1658dfb128e6a91330b24d7c320462fda87f3db0f64f4/typesafe_monads-0.5-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "32dda1458bb0bc3e4e3eb4ea847f63e2", "sha256": "e2ad2f656e1a51861186d9e10d80f0144f96b1e56a8e931836064141a2860d07" }, "downloads": -1, "filename": "typesafe-monads-0.5.tar.gz", "has_sig": false, "md5_digest": "32dda1458bb0bc3e4e3eb4ea847f63e2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6691, "upload_time": "2018-12-12T06:56:55", "url": "https://files.pythonhosted.org/packages/9b/08/0658732af08e92ad997de459ee39dea7f77f7ddbb68e6f06bec7f1f9f80d/typesafe-monads-0.5.tar.gz" } ], "0.6": [ { "comment_text": "", "digests": { "md5": "7a8f58ccddfdd107fd58404a05297fd8", "sha256": "2476d7929361ef441a0e2c31ee7eb4e8f6358818cdce301ee1c98b41f3fcad33" }, "downloads": -1, "filename": "typesafe_monads-0.6-py3-none-any.whl", "has_sig": false, "md5_digest": "7a8f58ccddfdd107fd58404a05297fd8", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 10680, "upload_time": "2018-12-13T04:27:18", "url": "https://files.pythonhosted.org/packages/ec/3c/359b2cdf35f077fceefb3698e1ec6619784ec425e6e262259db8851b2b05/typesafe_monads-0.6-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ba1aec525af0ef27c4122fe698df5f89", "sha256": "462f3771044fae44cc3d51ac5f898a4c5d97acb3e3d681a857c2366a2cbba168" }, "downloads": -1, "filename": "typesafe-monads-0.6.tar.gz", "has_sig": false, "md5_digest": "ba1aec525af0ef27c4122fe698df5f89", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8016, "upload_time": "2018-12-13T04:27:19", "url": "https://files.pythonhosted.org/packages/cc/ae/2c2dbe8917ddfb560d3a21cbc9474237f4e60ac12d5befb78d993c3342e4/typesafe-monads-0.6.tar.gz" } ], "0.7": [ { "comment_text": "", "digests": { "md5": "c46c50d1aaa2c9dd36926bf9006ef9fb", "sha256": "158a8d08815390cf9c451de64266a89d9702f243c86706012969fc87a7f23575" }, "downloads": -1, "filename": "typesafe_monads-0.7-py3-none-any.whl", "has_sig": false, "md5_digest": "c46c50d1aaa2c9dd36926bf9006ef9fb", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 12625, "upload_time": "2019-01-08T21:07:15", "url": "https://files.pythonhosted.org/packages/07/c7/1c94bd30e9d6ca8a954008c05b1564def65a3efd1d9a3143de6e7a708a95/typesafe_monads-0.7-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "db93e10c866762bf029fff06e78e958e", "sha256": "4116e38c628e289063269bebe9392dcce81ac1d3e35501c85e3b0549df5746ac" }, "downloads": -1, "filename": "typesafe-monads-0.7.tar.gz", "has_sig": false, "md5_digest": "db93e10c866762bf029fff06e78e958e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9308, "upload_time": "2019-01-08T21:07:16", "url": "https://files.pythonhosted.org/packages/4c/e7/24ce1ca68ce13cf6836f9570b01297fcac2436dae7b5c01904d9f5dc9755/typesafe-monads-0.7.tar.gz" } ], "0.8": [ { "comment_text": "", "digests": { "md5": "4091566b7b50554b6afaae972b553ecb", "sha256": "157f2685951578d1040af6a9909576972e5c3f3b5184b4649b6923d5ffa84755" }, "downloads": -1, "filename": "typesafe_monads-0.8-py3-none-any.whl", "has_sig": false, "md5_digest": "4091566b7b50554b6afaae972b553ecb", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 12638, "upload_time": "2019-06-11T15:59:56", "url": "https://files.pythonhosted.org/packages/04/e4/af1967e56e0791550e57e1b36ecfc2c3990d88740ee96ece37f68985d2c4/typesafe_monads-0.8-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "dbb39513f70d0c9f36bbed74b7339be7", "sha256": "1fb44a89587c737ce37e2f7dfb0e7e755a1029be9a6aeca75c8a80d8e06ebf69" }, "downloads": -1, "filename": "typesafe-monads-0.8.tar.gz", "has_sig": false, "md5_digest": "dbb39513f70d0c9f36bbed74b7339be7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9361, "upload_time": "2019-06-11T15:59:57", "url": "https://files.pythonhosted.org/packages/4b/83/1b34bc0aca3688844465c4908d16bcc798fb496006ab8a0c19042ab753e3/typesafe-monads-0.8.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "4091566b7b50554b6afaae972b553ecb", "sha256": "157f2685951578d1040af6a9909576972e5c3f3b5184b4649b6923d5ffa84755" }, "downloads": -1, "filename": "typesafe_monads-0.8-py3-none-any.whl", "has_sig": false, "md5_digest": "4091566b7b50554b6afaae972b553ecb", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 12638, "upload_time": "2019-06-11T15:59:56", "url": "https://files.pythonhosted.org/packages/04/e4/af1967e56e0791550e57e1b36ecfc2c3990d88740ee96ece37f68985d2c4/typesafe_monads-0.8-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "dbb39513f70d0c9f36bbed74b7339be7", "sha256": "1fb44a89587c737ce37e2f7dfb0e7e755a1029be9a6aeca75c8a80d8e06ebf69" }, "downloads": -1, "filename": "typesafe-monads-0.8.tar.gz", "has_sig": false, "md5_digest": "dbb39513f70d0c9f36bbed74b7339be7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9361, "upload_time": "2019-06-11T15:59:57", "url": "https://files.pythonhosted.org/packages/4b/83/1b34bc0aca3688844465c4908d16bcc798fb496006ab8a0c19042ab753e3/typesafe-monads-0.8.tar.gz" } ] }