{ "info": { "author": "Gr\u00e9gory Salvan", "author_email": "apieum@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 1 - Planning", "Environment :: Other Environment", "Intended Audience :: Developers", "License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "********\nLawvere\n********\n\n.. image:: https://pypip.in/v/lawvere/badge.png\n :target: https://pypi.python.org/pypi/lawvere\n\n---------------------------------------------------------------------\n\n**What ?**\n\nFunctionnal Tool: (de)composition with type checking, multiple dispatch.\n\n**Why ?**\n\nThere is a lot of functionnal tools in python: toolz, funcy, fn.py, Pymonads...\n\nThey are great but none of them do type checking which, in my opinion, is a big loss from functionnal paradigm view.\n\n**How ?**\n\nWith a complex and unmaintenable api: a single decorator called *\"arrow\"*.\n\nFor a *technical* explanation of arrows you can look at: `Understanding arrows `_\n\nFor a *theorical* explanation: *\"Conceptual Mathematics: A First Introduction to Categories\"* [F. William Lawvere, Stephen H. Schanuel] is good start.\n\n\n**Prerequisites**\n\nI strongly recommand to have at least notions about:\n * lambda calculi (Currying)\n * tuples in algebra notations (e.g. `signatures `_)\n * basics of graph theory (related to category theory - morphisms, domain, codomain...)\n\n\n---------------------------------------------------------------------\n\n**Table of Contents**\n\n\n.. contents::\n :local:\n :depth: 1\n :backlinks: none\n\n\n=============\nInstallation\n=============\n\nInstall it from pypi::\n\n pip install lawvere\n\nor from sources::\n\n git clone git@github.com:apieum/lawvere.git\n cd lawvere\n python setup.py install\n\n=====\nUsage\n=====\n\n------------\nQuick start:\n------------\n for impatients\n\n**arrow** take only two optionnal arguments:\n * the *domain* or *source*: it's a tuple of types (or just a type in case of 1-tuple)\n * the codomain or *target*: (a single type)\n\nIt returns a function decorator.\n\nSyntax is compatible for python 2.7 to 3.x..\nIn case you target 3.x versions only you can use annotations instead of \"*arrow*\" arguments.\n\"*arrow*\" arguments override annotations.\n\n\n**Code compatible with 2.x and 3.x python versions.**\n\n .. code-block:: python\n\n from lawvere import arrow\n\n # obviously you don't need to use named parameters\n # it's just to illustrate their meaning.\n @arrow(domain=(int, int), codomain=int)\n def add(x, y):\n return x + y\n\n # currying:\n add2 = add(2)\n\n assert add2(3) == 5\n assert add(1)(2) == 3 # successive calls\n\n # composition (pipe):\n # pass the result of first function to second\n add4 = add2 >> add2\n assert add4(1) == 5\n # composition (circle):\n # pass result of add(1) into add4\n add5 = add4 << add(1)\n assert add5(5) == 10\n\n # composed functions are tuples:\n assert isinstance(add4, tuple)\n assert add5[1] == add4\n\n # equality is checked over signatures:\n assert add(1) == add(1)\n assert add5 == add(1) >> add2 >> add2\n\n # operator precedence:\n assert add5 == add(1) >> (add2 << add2)\n assert add5 == add2 >> add2 << add(1)\n\n # Type Checking:\n type_checked = False\n try:\n add('a', 'b') == 'ab'\n except TypeError:\n type_checked = True\n\n assert type_checked, 'add should not exists for str types'\n\n\n # dispatch register\n # concat inherit arrow properties\n @add.register((str, str), str)\n def concat(x, y):\n return \"%s %s\" %(x, y)\n\n # can still call/curry... concat\n assert concat('a')('b') == 'a b'\n # add with str call concat\n assert add('a') == concat('a')\n\n # Concat is only defined for str\n type_checked = False\n try:\n assert concat(1, 2) == 3\n except TypeError:\n type_checked = True\n\n assert type_checked, 'concat should not exists for int types'\n\n # Type Checking when composing:\n try:\n add >> concat(y='b')\n except TypeError as exc:\n message = str(exc)\n # hope message is clear :)\n assert message == \"Cannot compose add -> int with concat(x:str=Undefined, y:str=b)\"\n # if composition was circle message would be:\n # ... concat -> str with add(x:int=Undefined, y:int=Undefined)\n\n\n\n**Code compatible with 3.x versions only.**\n\n .. code-block:: python\n\n from lawvere import arrow\n\n @arrow\n def add(x:int, y:int) -> int:\n return x + y\n\n # identical use as Python 2 #\n\n # Type Checking:\n type_checked = False\n try:\n add('a', 'b') == 'ab'\n except TypeError:\n type_checked = True\n\n assert type_checked, 'add should not exists for str types'\n\n # dispatch\n @add.register\n def concat(x:str, y:str) -> str:\n return \"%s %s\" %(x, y)\n\n assert concat('a', 'b') == 'a b'\n # now add exists for str types:\n assert add('a', 'b') == 'a b'\n\n # type is also checked when composing... see python 2 ex.\n\n\n\n\n\n\n===========\nDevelopment\n===========\n\nYour feedback, code review, improvements or bugs, and help to document is appreciated.\nYou can contact me by mail: apieum [at] gmail [dot] com\n\nTest recommended requirements::\n\n pip install -r dev-requirements.txt\n\nSometimes --spec-color doesn't function. Uninstall nosespec and nosecolor then reinstall nosecolor and nosespec separatly in this order (nosecolor first).\n\nLaunch tests::\n\n git clone git@github.com:apieum/lawvere.git\n cd lawvere\n nosetests --with-spec --spec-color ./lawvere\n # or with watch\n # nosetests --with-spec --spec-color --with-watch ./lawvere\n\n\n\n.. image:: https://secure.travis-ci.org/apieum/lawvere.png?branch=master\n :target: https://travis-ci.org/apieum/lawvere", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://www.python.org/pypi/lawvere", "keywords": null, "license": "LGPL", "maintainer": null, "maintainer_email": null, "name": "lawvere", "package_url": "https://pypi.org/project/lawvere/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/lawvere/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://www.python.org/pypi/lawvere" }, "release_url": "https://pypi.org/project/lawvere/0.1/", "requires_dist": null, "requires_python": null, "summary": "Easy To Use functionnal tool: (de)composition with type checking (curry, arrows), multiple dispatch", "version": "0.1" }, "last_serial": 1213984, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "7deacda77e64333a8f6128627162077d", "sha256": "e09036d8599c88bfe2dcecb08ca72c65c8f5fd0e72343c4cba837ed818ce19de" }, "downloads": -1, "filename": "lawvere-0.1.tar.gz", "has_sig": false, "md5_digest": "7deacda77e64333a8f6128627162077d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16466, "upload_time": "2014-09-05T12:04:43", "url": "https://files.pythonhosted.org/packages/d1/c8/eb7955963853d6f937494801cc29e2b82d1ebd22dc32f18d3ed59166b5de/lawvere-0.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "7deacda77e64333a8f6128627162077d", "sha256": "e09036d8599c88bfe2dcecb08ca72c65c8f5fd0e72343c4cba837ed818ce19de" }, "downloads": -1, "filename": "lawvere-0.1.tar.gz", "has_sig": false, "md5_digest": "7deacda77e64333a8f6128627162077d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16466, "upload_time": "2014-09-05T12:04:43", "url": "https://files.pythonhosted.org/packages/d1/c8/eb7955963853d6f937494801cc29e2b82d1ebd22dc32f18d3ed59166b5de/lawvere-0.1.tar.gz" } ] }