{ "info": { "author": "Philip Xu", "author_email": "pyx@xrefactor.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "==========================================\nHy Monad Notation - a monad library for Hy\n==========================================\n\n\nIntroduction\n============\n\nHymn is a monad library for Hy/Python, with do notation for monad\ncomprehension.\n\nCode are better than words.\n\nThe continuation monad\n\n.. code-block:: clojure\n\n => (import [hymn.types.continuation [cont-m call-cc]])\n => ;; computations in continuation passing style\n => (defn double [x] (cont-m.unit (* x 2)))\n => (setv length (cont-m.monadic len))\n => ;; chain with bind\n => (.run (>> (cont-m.unit [1 2 3]) length double))\n 6\n => (defn square [n] (call-cc (fn [k] (k (** n 2)))))\n => (.run (square 12))\n 144\n => (.run (square 12) inc)\n 145\n => (.run (square 12) str)\n '144'\n => (require [hymn.macros [do-monad]])\n => (.run (do-monad [sqr (square 42)] (.format \"answer^2 = {}\" sqr)))\n 'answer^2 = 1764'\n\nThe either monad\n\n.. code-block:: clojure\n\n => (import [hymn.types.either [Left Right either failsafe]])\n => (require [hymn.macros [do-monad]])\n => ;; do notation with either monad\n => (do-monad [a (Right 1) b (Right 2)] (/ a b))\n Right(0.5)\n => (do-monad [a (Right 1) b (Left 'nan)] (/ a b))\n Left(HySymbol('nan'))\n => ;; failsafe is a function decorator that wraps return value into either\n => (setv safe-div (failsafe /))\n => ;; returns Right if nothing wrong\n => (safe-div 4 2)\n Right(2.0)\n => ;; returns Left when bad thing happened, like exception being thrown\n => (safe-div 1 0)\n Left(ZeroDivisionError('division by zero',))\n => ;; function either tests the value and calls functions accordingly\n => (either print inc (safe-div 4 2))\n 3.0\n => (either print inc (safe-div 1 0))\n division by zero\n\nThe identity monad\n\n.. code-block:: clojure\n\n => (import [hymn.types.identity [identity-m]])\n => (require [hymn.macros [do-monad]])\n => ;; do notation with identity monad is like let binding\n => (do-monad [a (identity-m 1) b (identity-m 2)] (+ a b))\n Identity(3)\n\nThe lazy monad\n\n.. code-block:: clojure\n\n => (import [hymn.types.lazy [force]])\n => (require [hymn.types.lazy [lazy]])\n => ;; lazy computation implemented as monad\n => ;; macro lazy creates deferred computation\n => (setv a (lazy (print \"evaluate a\") 42))\n => ;; the computation is deferred, notice the value is shown as '_'\n => a\n Lazy(_)\n => ;; evaluate it\n => (.evaluate a)\n evaluate a\n 42\n => ;; now the value is cached\n => a\n Lazy(42)\n => ;; calling evaluate again will not trigger the computation\n => (.evaluate a)\n 42\n => (setv b (lazy (print \"evaluate b\") 21))\n => b\n Lazy(_)\n => ;; force evaluate the computation, same as calling .evaluate on the monad\n => (force b)\n evaluate b\n 21\n => ;; force on values other than lazy return the value unchanged\n => (force 42)\n 42\n => (require [hymn.macros [do-monad]])\n => ;; do notation with lazy monad\n => (setv c (do-monad [x (lazy (print \"get x\") 1) y (lazy (print \"get y\") 2)] (+ x y)))\n => ;; the computation is deferred\n => c\n Lazy(_)\n => ;; do it!\n => (force c)\n get x\n get y\n 3\n => ;; again\n => (force c)\n 3\n\nThe list monad\n\n.. code-block:: clojure\n\n => (import [hymn.types.list [list-m]])\n => (require [hymn.macros [do-monad]])\n => ;; use list-m contructor to turn sequence into list monad\n => (setv xs (list-m (range 2)))\n => (setv ys (list-m (range 3)))\n => ;; do notation with list monad is list comprehension\n => (list (do-monad [x xs y ys :when (not (zero? y))] (/ x y)) )\n [0.0, 0.0, 1.0, 0.5]\n => (require [hymn.types.list [~]])\n => ;; ~ is the tag macro for list-m\n => (list (do-monad [x #~(range 2) y #~(range 3) :when (not (zero? y))] (/ x y)) )\n [0.0, 0.0, 1.0, 0.5]\n\nThe maybe monad\n\n.. code-block:: clojure\n\n => (import [hymn.types.maybe [Just Nothing maybe]])\n => (require [hymn.macros [do-monad]])\n => ;; do notation with maybe monad\n => (do-monad [a (Just 1) b (Just 1)] (/ a b))\n Just(1.0)\n => ;; Nothing yields Nothing\n => (do-monad [a Nothing b (Just 1)] (/ a b))\n Nothing\n => ;; maybe is a function decorator that wraps return value into maybe\n => ;; a safe-div with maybe monad\n => (setv safe-div (maybe /))\n => (safe-div 42 42)\n Just(1.0)\n => (safe-div 42 'answer)\n Nothing\n => (safe-div 42 0)\n Nothing\n\nThe reader monad\n\n.. code-block:: clojure\n\n => (import [hymn.types.reader [lookup]])\n => (require [hymn.macros [do-monad]])\n => ;; do notation with reader monad, lookup assumes the environment is subscriptable\n => (setv r (do-monad [a (lookup 'a) b (lookup 'b)] (+ a b)))\n => ;; run reader monad r with environment\n => (.run r {'a 1 'b 2})\n 3\n\nThe state monad\n\n.. code-block:: clojure\n\n => (import [hymn.types.state [lookup set-value]])\n => (require [hymn.macros [do-monad]])\n => ;; do notation with state monad, set-value sets the value with key in the state\n => (setv s (do-monad [a (lookup 'a) _ (set-value 'b (inc a))] a))\n => ;; run state monad s with initial state\n => (.run s {'a 1})\n (1, {HySymbol('a'): 1, HySymbol('b'): 2})\n\nThe writer monad\n\n.. code-block:: clojure\n\n => (import [hymn.types.writer [tell]])\n => (require [hymn.macros [do-monad]])\n => ;; do notation with writer monad\n => (do-monad [_ (tell \"hello\") _ (tell \" world\")] None)\n StrWriter((None, 'hello world'))\n => ;; int is monoid, too\n => (.execute (do-monad [_ (tell 1) _ (tell 2) _ (tell 3)] None))\n 6\n\nOperations on monads\n\n.. code-block:: clojure\n\n => (import [hymn.operations [lift]])\n => ;; lift promotes function into monad\n => (setv m+ (lift +))\n => ;; lifted function can work on any monad\n => ;; on the maybe monad\n => (import [hymn.types.maybe [Just Nothing]])\n => (m+ (Just 1) (Just 2))\n Just(3)\n => (m+ (Just 1) Nothing)\n Nothing\n => ;; on the either monad\n => (import [hymn.types.either [Left Right]])\n => (m+ (Right 1) (Right 2))\n Right(3)\n => (m+ (Left 1) (Right 2))\n Left(1)\n => ;; on the list monad\n => (import [hymn.types.list [list-m]])\n => (list (m+ (list-m \"ab\") (list-m \"123\")))\n ['a1', 'a2', 'a3', 'b1', 'b2', 'b3']\n => (list (m+ (list-m \"+-\") (list-m \"123\") (list-m \"xy\")))\n ['+1x', '+1y', '+2x', '+2y', '+3x', '+3y', '-1x', '-1y', '-2x', '-2y', '-3x', '-3y']\n => ;; can be used as normal function\n => (reduce m+ [(Just 1) (Just 2) (Just 3)])\n Just(6)\n => (reduce m+ [(Just 1) Nothing (Just 3)])\n Nothing\n => ;; <- is an alias of lookup\n => (import [hymn.types.reader [<-]])\n => (require [hymn.macros [^]])\n => ;; ^ is the tag macro for lift\n => (setv p (#^ print (<- 'message) :end (<- 'end)))\n => (.run p {'message \"Hello world\" 'end \"!\\n\"})\n Hello world!\n => ;; random number - linear congruential generator\n => (import [hymn.types.state [get-state set-state]])\n => (setv random (>> get-state (fn [s] (-> s (* 69069) inc (% (** 2 32)) set-state))))\n => (.run random 1234)\n (1234, 85231147)\n => ;; random can be even shorter by using modify\n => (import [hymn.types.state [modify]])\n => (setv random (modify (fn [s] (-> s (* 69069) inc (% (** 2 32))))))\n => (.run random 1234)\n (1234, 85231147)\n => ;; use replicate to do computation repeatly\n => (import [hymn.operations [replicate]])\n => (.evaluate (replicate 5 random) 42)\n [42, 2900899, 2793697416, 2186085609, 1171637142]\n => ;; sequence on writer monad\n => (import [hymn.operations [sequence]])\n => (import [hymn.types.writer [tell]])\n => (.execute (sequence (map tell (range 1 101))))\n 5050\n\nUsing Hymn in Python\n\n.. code-block:: python\n\n >>> from hymn.dsl import *\n >>> sequence(map(tell, range(1, 101))).execute()\n 5050\n >>> msum = lift(sum)\n >>> msum(sequence(map(maybe(int), \"12345\")))\n Just(15)\n >>> msum(sequence(map(maybe(int), \"12345a\")))\n Nothing\n >>> @failsafe\n ... def safe_div(a, b):\n ... return a / b\n ...\n >>> safe_div(1.0, 2)\n Right(0.5)\n >>> safe_div(1, 0)\n Left(ZeroDivisionError(...))\n\n\nRequirements\n============\n\n- hy >= 0.14.0\n\nFor hy version 0.13, please install hymn 0.7.\n\nFor hy version 0.12, please install hymn 0.6.\n\nFor hy version 0.11 and earlier, please install hymn 0.5.\n\nSee Changelog section in documentation for details.\n\n\nInstallation\n============\n\nInstall from PyPI::\n\n pip install hymn\n\nInstall from source, download source package, decompress, then :code:`cd` into\nsource directory, run::\n\n make install\n\n\nLicense\n=======\n\nBSD New, see LICENSE for details.\n\n\nLinks\n=====\n\nDocumentation:\n https://hymn.readthedocs.io/\n\nIssue Tracker:\n https://github.com/pyx/hymn/issues/\n\nSource Package @ PyPI:\n https://pypi.python.org/pypi/hymn/\n\nMercurial Repository @ bitbucket:\n https://bitbucket.org/pyx/hymn/\n\nGit Repository @ Gitlab:\n https://gitlab.com/pyx/hymn/\n\nGit Repository @ Github:\n https://github.com/pyx/hymn/\n\n\n", "description_content_type": "", "docs_url": null, "download_url": "https://bitbucket.org/pyx/hymn/get/0.8.tar.bz2", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/pyx/hymn/", "keywords": "hy lisp monad functional programming", "license": "BSD-New", "maintainer": "", "maintainer_email": "", "name": "hymn", "package_url": "https://pypi.org/project/hymn/", "platform": "any", "project_url": "https://pypi.org/project/hymn/", "project_urls": { "Download": "https://bitbucket.org/pyx/hymn/get/0.8.tar.bz2", "Homepage": "https://github.com/pyx/hymn/" }, "release_url": "https://pypi.org/project/hymn/0.8/", "requires_dist": [ "hy (>=0.14.0)", "twine; extra == 'dev'", "Sphinx; extra == 'doc'", "flake8; extra == 'test'", "pytest; extra == 'test'", "tox; extra == 'test'" ], "requires_python": "", "summary": "Hy Monad Notation - a monad library for Hy", "version": "0.8" }, "last_serial": 3808919, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "2c3290eff38108eef4fc7f75ae253344", "sha256": "cb591feb5c73c5d0ca0a4463b05fecf1a9888834e644583edec1d42ee5bae847" }, "downloads": -1, "filename": "hymn-0.1.tar.gz", "has_sig": true, "md5_digest": "2c3290eff38108eef4fc7f75ae253344", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 33678, "upload_time": "2015-12-10T02:03:52", "url": "https://files.pythonhosted.org/packages/e3/80/a502e7faf3a2d83c7333eb57ee6482d7f9931de941c456422cb09e040088/hymn-0.1.tar.gz" } ], "0.1dev": [], "0.2": [ { "comment_text": "", "digests": { "md5": "48aa24de112685f7de46f003459124c2", "sha256": "23abc35a3e62bac9ef7ea766aa8268e97a83189345457ea66b8b0ee59810235d" }, "downloads": -1, "filename": "hymn-0.2.tar.gz", "has_sig": true, "md5_digest": "48aa24de112685f7de46f003459124c2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 36375, "upload_time": "2015-12-15T11:34:31", "url": "https://files.pythonhosted.org/packages/42/a1/b11ede123109b434ace2913887531be3555a52c859057785b95f5d49366a/hymn-0.2.tar.gz" } ], "0.3": [ { "comment_text": "", "digests": { "md5": "065aa126e36491f462ef4a5a0789c073", "sha256": "5eb9e9914cd8de411eb9f04d131f2acc724dc648ea66d1fdc367ed1d6fa5d601" }, "downloads": -1, "filename": "hymn-0.3.tar.gz", "has_sig": true, "md5_digest": "065aa126e36491f462ef4a5a0789c073", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 40902, "upload_time": "2016-01-02T00:59:20", "url": "https://files.pythonhosted.org/packages/1f/04/b4c39c5a3284267bb1e7bb6dc2e9de2c0306a5d742b4cb33ea7204f30a4f/hymn-0.3.tar.gz" } ], "0.4": [], "0.5": [ { "comment_text": "", "digests": { "md5": "b086a153ffc1097dab12d8f7b4066376", "sha256": "3efaa194a444c7605285395f61878f77aab2c6c9aa52eeaa8d7b539d1077369d" }, "downloads": -1, "filename": "hymn-0.5.tar.gz", "has_sig": true, "md5_digest": "b086a153ffc1097dab12d8f7b4066376", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 40218, "upload_time": "2016-01-26T01:42:25", "url": "https://files.pythonhosted.org/packages/95/a2/f76152eaf169e50e2eee09de98c710f94bb49918c485e90e96af70212d8f/hymn-0.5.tar.gz" } ], "0.6": [ { "comment_text": "", "digests": { "md5": "7278383dd5d765652d536a330f8bc410", "sha256": "4ef353aa2ad7f09b34a36c37c8980e3a615eae84954af1dc3f2825db3581e1fc" }, "downloads": -1, "filename": "hymn-0.6-py2.py3-none-any.whl", "has_sig": true, "md5_digest": "7278383dd5d765652d536a330f8bc410", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 24097, "upload_time": "2017-01-26T06:35:49", "url": "https://files.pythonhosted.org/packages/c6/d4/e3b0d66dde0b6e23f846957ebd0405ce860b6357b7e1c063a68bb4f07fea/hymn-0.6-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "4d90f0c2528cc87a8dddf045c7b781fc", "sha256": "1649c9a79c8c2d9fe0f9b2c0c0bcbff02ede52105db7597b80475bd83df53bd2" }, "downloads": -1, "filename": "hymn-0.6.tar.gz", "has_sig": true, "md5_digest": "4d90f0c2528cc87a8dddf045c7b781fc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 43596, "upload_time": "2017-01-26T06:35:50", "url": "https://files.pythonhosted.org/packages/fa/43/a76f11b22aea46036ed60b217403d01da3836c669fd0ce6a659fb2b0d3d6/hymn-0.6.tar.gz" } ], "0.7": [ { "comment_text": "", "digests": { "md5": "dce1afc3675221c77e0835a5e35d4917", "sha256": "2810d76e37be246d8e55ed2c8c5c79fd758f8aee9717539758243c032897983b" }, "downloads": -1, "filename": "hymn-0.7-py2.py3-none-any.whl", "has_sig": true, "md5_digest": "dce1afc3675221c77e0835a5e35d4917", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 24023, "upload_time": "2017-07-03T07:59:22", "url": "https://files.pythonhosted.org/packages/7e/91/1c75b1525f6fc6101540638daa6fb4cf2112a5e412062cca7e5ac57aa880/hymn-0.7-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "8c49fb31adb0103ee60fe4777db6836a", "sha256": "48238363ce7199ac36d170fc820516b1893f228cb6f16e2d4118e55002b90a9b" }, "downloads": -1, "filename": "hymn-0.7.tar.gz", "has_sig": true, "md5_digest": "8c49fb31adb0103ee60fe4777db6836a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 43285, "upload_time": "2017-07-03T07:59:24", "url": "https://files.pythonhosted.org/packages/74/20/3dc75dd69cc2a668679078b0ab51efa2da753a419b66a4dd32b321c641ba/hymn-0.7.tar.gz" } ], "0.8": [ { "comment_text": "", "digests": { "md5": "1edbfe697b9c490188d7568464cad70f", "sha256": "bdfb0afb898c3dc3db43db327a87a08bd51e14aa3df092b03e7fb84b04c3933e" }, "downloads": -1, "filename": "hymn-0.8-py2.py3-none-any.whl", "has_sig": true, "md5_digest": "1edbfe697b9c490188d7568464cad70f", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 20331, "upload_time": "2018-04-26T03:27:23", "url": "https://files.pythonhosted.org/packages/29/6f/07ce056835aea2defff0ee3e503a6e80ecdbccfa8100e96a10b04b3e466f/hymn-0.8-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "15810f4943aa0c5e8f20423e9ccaf5f4", "sha256": "527356ea5ec157fb34a70bdd5cb955927a9ddd917fb08c91acbb95bea9d72d4b" }, "downloads": -1, "filename": "hymn-0.8.tar.gz", "has_sig": true, "md5_digest": "15810f4943aa0c5e8f20423e9ccaf5f4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 42347, "upload_time": "2018-04-26T03:27:24", "url": "https://files.pythonhosted.org/packages/72/3d/9824b01e7e819a4314da05bca1de7810592515330d32c5b227a44686e9ea/hymn-0.8.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "1edbfe697b9c490188d7568464cad70f", "sha256": "bdfb0afb898c3dc3db43db327a87a08bd51e14aa3df092b03e7fb84b04c3933e" }, "downloads": -1, "filename": "hymn-0.8-py2.py3-none-any.whl", "has_sig": true, "md5_digest": "1edbfe697b9c490188d7568464cad70f", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 20331, "upload_time": "2018-04-26T03:27:23", "url": "https://files.pythonhosted.org/packages/29/6f/07ce056835aea2defff0ee3e503a6e80ecdbccfa8100e96a10b04b3e466f/hymn-0.8-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "15810f4943aa0c5e8f20423e9ccaf5f4", "sha256": "527356ea5ec157fb34a70bdd5cb955927a9ddd917fb08c91acbb95bea9d72d4b" }, "downloads": -1, "filename": "hymn-0.8.tar.gz", "has_sig": true, "md5_digest": "15810f4943aa0c5e8f20423e9ccaf5f4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 42347, "upload_time": "2018-04-26T03:27:24", "url": "https://files.pythonhosted.org/packages/72/3d/9824b01e7e819a4314da05bca1de7810592515330d32c5b227a44686e9ea/hymn-0.8.tar.gz" } ] }