Skip to content

Commit

Permalink
Update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Maxim Avanov committed Jun 10, 2019
1 parent f70e79d commit e46e1c9
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 2 deletions.
88 changes: 88 additions & 0 deletions docs/quickstart_guide.rst
Expand Up @@ -164,13 +164,101 @@ Supported types by default
* ``typing.Tuple``
* ``typing.Dict``
* ``typing.Mapping``
* ``typeit.sums.SumType``
* ``enum.Enum`` derivatives
* ``pathlib.Path`` derivatives
* ``typing_extensions.Literal``
* ``pyrsistent.typing.PVector``
* ``pyrsistent.typing.PMap``


Sum Type
--------

There are many ways to describe what a Sum Type (Tagged Union) is. Here's just a few of them:

* `Wikipedia <https://en.wikipedia.org/wiki/Tagged_union>`_ describes it as "a data structure used
to hold a value that could take on several different, but fixed, types.
Only one of the types can be in use at any one time, and a tag explicitly indicates which one
is in use. It can be thought of as a type that has several “cases”, each of which should be handled
correctly when that type is manipulated";

* or you can think of Sum Types as data types that have more than one constructor, where each constructor
accepts its own set of input data;

* or even simpler, as a generalized version of Enums, with some extra features.

``typeit`` provides a limited implementation of Sum Types, that have functionality similar to default Python Enums,
plus the ability of each tag to hold a value.

A new SumType is defined with the following signature

.. code-block:: python
from typeit.sums import SumType
class PaymentMethod(SumType):
class Cash:
amount: Money
class Card:
amount: Money
card: CardCredentials
class Phone:
amount: Money
provider: MobilePaymentProvider
class JustThankYou:
pass
``PaymentMethod`` is a new Tagged Union (which is another name for a Sum Type, remember), that consists
of four distinct possibilities: ``Cash``, ``Card``, ``Phone``, and ``JustThankYou``.
These possibilities are called tags (or variants, or constructors) of ``PaymentMethod``.
In other words, any instance of ``PaymentMethod`` is either ``Cash`` or ``Card`` or ``Phone`` or ``JustThankYou``,
and is never two or more of them at the same time.

Now, let's observe the properties of this new type:

.. code-block:: python
>>> adam_paid = PaymentMethod.Cash(amount=Money('USD', 10))
>>> jane_paid = PaymentMethod.Card(amount=Money('GBP', 8),
... card=CardCredentials(number='1234 5678 9012 3456',
... holder='Jane Austen',
... validity='12/24',
... secret='***'))
>>> fred_paid = PaymentMethod.JustThankYou()
>>>
>>> assert type(adam_paid) is type(jane_paid) is type(fred_paid) is PaymentMethod
>>>
>>> assert isinstance(adam_paid, PaymentMethod)
>>> assert isinstance(jane_paid, PaymentMethod)
>>> assert isinstance(fred_paid, PaymentMethod)
>>>
>>> assert isinstance(adam_paid, PaymentMethod.Cash)
>>> assert isinstance(jane_paid, PaymentMethod.Card)
>>> assert isinstance(fred_paid, PaymentMethod.JustThankYou)
>>>
>>> assert not isinstance(adam_paid, PaymentMethod.Card)
>>> assert not isinstance(adam_paid, PaymentMethod.JustThankYou)
>>>
>>> assert not isinstance(jane_paid, PaymentMethod.Cash)
>>> assert not isinstance(jane_paid, PaymentMethod.JustThankYou)
>>>
>>> assert not isinstance(fred_paid, PaymentMethod.Cash)
>>> assert not isinstance(fred_paid, PaymentMethod.Card)
>>>
>>> assert not isinstance(adam_paid, PaymentMethod.Phone)
>>> assert not isinstance(jane_paid, PaymentMethod.Phone)
>>> assert not isinstance(fred_paid, PaymentMethod.Phone)
As you can see, every variant constructs an instance of the same type ``PaymentMethod``,
and yet, every instance is identified with a distinct tag.


Flags
-----

Expand Down
9 changes: 9 additions & 0 deletions tests/test_parser.py
Expand Up @@ -288,6 +288,15 @@ class X(NamedTuple):
assert x.x.name == 'Name'
assert dict_x(x) == x_data

with pytest.raises(typeit.Invalid):
# version is missing
x = mk_x({
'x': ('right', {
'data': {'value': 'Value'},
'name': 'Name',
})
})


def test_enum_unions_serialization():
class E0(Enum):
Expand Down
2 changes: 0 additions & 2 deletions tests/test_sums.py
Expand Up @@ -125,5 +125,3 @@ class Right: ...

assert x.errmsg == 'Error'
assert y.payload == {'success': True}


0 comments on commit e46e1c9

Please sign in to comment.