Skip to content

Commit 93965d0

Browse files
committed
Improves docs
1 parent 91f9dcb commit 93965d0

File tree

1 file changed

+47
-1
lines changed

1 file changed

+47
-1
lines changed

docs/pages/concept.rst

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ Now we can be sure that our ``List[int]`` can be checked in runtime:
195195
196196
>>> assert isinstance([1, 2, 3], ListOfInt) is True
197197
>>> assert isinstance([1, 'a'], ListOfInt) is False
198+
>>> assert isinstance([], ListOfInt) is False # empty
198199
199200
And now we can use it with ``classes``:
200201

@@ -225,7 +226,52 @@ This solution still has several problems:
225226
and ``mypy`` thinks that it is ``ListOfInt``
226227
(a fake type that we are not ever using directly)
227228

228-
To solve all these problems we recommend to use ``phantom-types`` package.
229+
delegate argument
230+
~~~~~~~~~~~~~~~~~
231+
232+
To solve the first problem,
233+
we can use ``delegate=`` argument to ``.instance`` call:
234+
235+
.. code:: python
236+
237+
>>> from classes import typeclass
238+
>>> from typing import List
239+
240+
>>> @typeclass
241+
... def sum_all(instance) -> int:
242+
... ...
243+
244+
>>> @sum_all.instance(List[int], delegate=ListOfInt)
245+
... def _sum_all_list_int(instance: List[int]) -> int:
246+
... return sum(instance)
247+
248+
>>> your_list = [1, 2, 3]
249+
>>> assert sum_all(your_list) == 6
250+
251+
What happens here? When defining an instance with ``delegate`` argument,
252+
what we really do is: we add our ``delegate``
253+
into a special registry inside ``sum_all`` typeclass.
254+
255+
This registry is using ``isinstance``
256+
to find handler that fit the defined predicate.
257+
It has the highest priority among other dispatch methods.
258+
259+
This allows to sync both runtime and ``mypy`` behavior:
260+
261+
.. code:: python
262+
263+
>>> # Mypy will raise a type error:
264+
>>> # Argument 1 to "sum_all" has incompatible type "List[str]"; expected "List[int]"
265+
266+
>>> sum_all(['a', 'b'])
267+
Traceback (most recent call last):
268+
...
269+
NotImplementedError: Missing matched typeclass instance for type: list
270+
271+
Phantom types
272+
~~~~~~~~~~~~~
273+
274+
To solve problems ``2`` and ``3`` we recommend to use ``phantom-types`` package.
229275
230276
First, you need to define a "phantom" type
231277
(it is called "phantom" because it does not exist in runtime):

0 commit comments

Comments
 (0)