@@ -118,4 +118,107 @@ class R: ...
118118static_assert(is_equivalent_to(Intersection[tuple[P | Q], R], Intersection[tuple[Q | P], R]))
119119```
120120
121+ ## Callable
122+
123+ ### Equivalent
124+
125+ For an equivalence relationship, the default value does not necessarily need to be the same but if
126+ the parameter in one of the callable has a default value then the corresponding parameter in the
127+ other callable should also have a default value.
128+
129+ ``` py
130+ from knot_extensions import CallableTypeFromFunction, is_equivalent_to, static_assert
131+ from typing import Callable
132+
133+ def c1 (a : int , / , b : float , c : bool = False , * args : int , d : int = 1 , e : str , ** kwargs : float ) -> None : ...
134+ def c2 (a : int , / , b : float , c : bool = True , * args : int , d : int = 2 , e : str , ** kwargs : float ) -> None : ...
135+
136+ static_assert(is_equivalent_to(CallableTypeFromFunction[c1], CallableTypeFromFunction[c2]))
137+ ```
138+
139+ ### Not equivalent
140+
141+ There are multiple cases when two callable types are not equivalent which are enumerated below.
142+
143+ ``` py
144+ from knot_extensions import CallableTypeFromFunction, is_equivalent_to, static_assert
145+ from typing import Callable
146+ ```
147+
148+ When the number of parameters is different:
149+
150+ ``` py
151+ def f1 (a : int ) -> None : ...
152+ def f2 (a : int , b : int ) -> None : ...
153+
154+ static_assert(not is_equivalent_to(CallableTypeFromFunction[f1], CallableTypeFromFunction[f2]))
155+ ```
156+
157+ When either of the callable types uses a gradual form for the parameters:
158+
159+ ``` py
160+ static_assert(not is_equivalent_to(Callable[... , None ], Callable[[int ], None ]))
161+ static_assert(not is_equivalent_to(Callable[[int ], None ], Callable[... , None ]))
162+ ```
163+
164+ When the return types are not equivalent or absent in one or both of the callable types:
165+
166+ ``` py
167+ def f3 (): ...
168+ def f4 () -> None : ...
169+
170+ static_assert(not is_equivalent_to(Callable[[], int ], Callable[[], None ]))
171+ static_assert(not is_equivalent_to(CallableTypeFromFunction[f3], CallableTypeFromFunction[f3]))
172+ static_assert(not is_equivalent_to(CallableTypeFromFunction[f3], CallableTypeFromFunction[f4]))
173+ static_assert(not is_equivalent_to(CallableTypeFromFunction[f4], CallableTypeFromFunction[f3]))
174+ ```
175+
176+ When the parameter names are different:
177+
178+ ``` py
179+ def f5 (a : int ) -> None : ...
180+ def f6 (b : int ) -> None : ...
181+
182+ static_assert(not is_equivalent_to(CallableTypeFromFunction[f5], CallableTypeFromFunction[f6]))
183+ ```
184+
185+ When only one of the callable types has parameter names:
186+
187+ ``` py
188+ static_assert(not is_equivalent_to(CallableTypeFromFunction[f5], Callable[[int ], None ]))
189+ ```
190+
191+ When the parameter kinds are different:
192+
193+ ``` py
194+ def f7 (a : int , / ) -> None : ...
195+ def f8 (a : int ) -> None : ...
196+
197+ static_assert(not is_equivalent_to(CallableTypeFromFunction[f7], CallableTypeFromFunction[f8]))
198+ ```
199+
200+ When the annotated types of the parameters are not equivalent or absent in one or both of the
201+ callable types:
202+
203+ ``` py
204+ def f9 (a : int ) -> None : ...
205+ def f10 (a : str ) -> None : ...
206+ def f11 (a ) -> None : ...
207+
208+ static_assert(not is_equivalent_to(CallableTypeFromFunction[f9], CallableTypeFromFunction[f10]))
209+ static_assert(not is_equivalent_to(CallableTypeFromFunction[f10], CallableTypeFromFunction[f11]))
210+ static_assert(not is_equivalent_to(CallableTypeFromFunction[f11], CallableTypeFromFunction[f10]))
211+ static_assert(not is_equivalent_to(CallableTypeFromFunction[f11], CallableTypeFromFunction[f11]))
212+ ```
213+
214+ When the default value for a parameter is present only in one of the callable type:
215+
216+ ``` py
217+ def f12 (a : int ) -> None : ...
218+ def f13 (a : int = 2 ) -> None : ...
219+
220+ static_assert(not is_equivalent_to(CallableTypeFromFunction[f12], CallableTypeFromFunction[f13]))
221+ static_assert(not is_equivalent_to(CallableTypeFromFunction[f13], CallableTypeFromFunction[f12]))
222+ ```
223+
121224[ the equivalence relation ] : https://typing.readthedocs.io/en/latest/spec/glossary.html#term-equivalent
0 commit comments