The Either Monad
================

.. automodule:: hymn.types.either
  :members:
  :show-inheritance:

.. autodata:: zero

.. function:: to_either

  alias of :meth:`~Either.from_value`


Hy Specific API
---------------

.. class:: either-m

  alias of :class:`Either`


Reader Macro
^^^^^^^^^^^^

.. function:: | [f]

  turn ``f`` into monadic function with :func:`failsafe`


Functions
^^^^^^^^^

.. function:: ->either
.. function:: to-either

  alias of :func:`Either.from_value`

.. function:: left?

  alias of :func:`is_left`

.. function:: right?

  alias of :func:`is_right`


Examples
--------


Comparison
^^^^^^^^^^

Either are comparable if the wrapped values are comparable. :class:`Right` is
greater than :data:`Left` in any case.

.. code-block:: clojure

  => (import [hymn.types.either [Left Right]])
  => (> (Right 2) (Right 1))
  True
  => (< (Left 2) (Left 1))
  False
  => (> (Left 2) (Right 1))
  False


Do Notation
^^^^^^^^^^^

.. code-block:: clojure

  => (require hymn.dsl)
  => (import [hymn.types.either [Left Right]])
  => (do-monad [a (Right 1) b (Right 2)] (+ a b))
  Right(3)
  => (do-monad [a (Left 1) b (Right 2)] (+ a b))
  Left(1)


Do Notation with :when
^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: clojure

  => (require hymn.dsl)
  => (import [hymn.types.either [either-m]])
  => (defn safe-div [a b]
  ...   (do-monad-with either-m [:when (not (zero? b))] (/ a b)))
  => (safe-div 1 2)
  Right(0.5)
  => (safe-div 1 0)
  Left('unknown error')


Operations
^^^^^^^^^^

:func:`->either` create an :class:`Either` from a value

.. code-block:: clojure

  => (import [hymn.types.either [->either]])
  => (->either 42)
  Right(42)
  => (->either nil)
  Left(None)

use :func:`left?` and :func:`right?` to test the type

.. code-block:: clojure

  => (import [hymn.types.either [Left Right left? right?]])
  => (right? (Right 42))
  True
  => (left? (Left nil))
  True

:func:`either` applies function to value in the monad depending on the type

.. code-block:: clojure

  => (import [hymn.types.either [Left Right either]])
  => (either print inc (Left 1))
  1
  => (either print inc (Right 1))
  2

:func:`failsafe` turns function into monadic one

.. code-block:: clojure

  => (import [hymn.types.either [failsafe]])
  => (with-decorator failsafe (defn add1 [n] (inc (int n))))
  => (add1 "41")
  Right(42)
  => (add1 "nan")
  Left(ValueError("invalid literal for int() with base 10: 'nan'",))
  => (def safe-div (failsafe /))
  => (safe-div 1 2)
  Right(0.5)
  => (safe-div 1 0)
  Left(ZeroDivisionError('division by zero',))


Reader Macro
^^^^^^^^^^^^

.. code-block:: clojure

  => (require hymn.types.either)
  => (#|int "42")
  Right(42)
  => (#|int "nan")
  Left(ValueError("invalid literal for int() with base 10: 'nan'",))
  => (def safe-div #|/)
  => (safe-div 1 2)
  Right(0.5)
  => (safe-div 1 0)
  Left(ZeroDivisionError('division by zero',))
