@@ -195,6 +195,7 @@ Now we can be sure that our ``List[int]`` can be checked in runtime:
195
195
196
196
>> > assert isinstance ([1 , 2 , 3 ], ListOfInt) is True
197
197
>> > assert isinstance ([1 , ' a' ], ListOfInt) is False
198
+ >> > assert isinstance ([], ListOfInt) is False # empty
198
199
199
200
And now we can use it with ``classes ``:
200
201
@@ -225,7 +226,52 @@ This solution still has several problems:
225
226
and ``mypy `` thinks that it is ``ListOfInt ``
226
227
(a fake type that we are not ever using directly)
227
228
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.
229
275
230
276
First, you need to define a " phantom" type
231
277
(it is called " phantom" because it does not exist in runtime):
0 commit comments