multimethod icon indicating copy to clipboard operation
multimethod copied to clipboard

Dispatching on type of NewType

Open asitstands opened this issue 1 month ago • 2 comments

from multimethod import multimethod
from typing import NewType

Int = NewType("Int", int)

@multimethod
def foo(_: type[Int]):
    print("A")

foo(Int) # Currently DispatchError is raised. No method found.
foo(int) # Currently prints "A".

It would be helpful if foo(Int) is dispatched to the defined method. However, for foo(int), I'm not sure what is correct behavior. Should it raise a DispatchError? The purpose of NewType is primarily to define a "distinct" type in type checking situation. So, I think raising an exception makes sense.

asitstands avatar Nov 29 '25 18:11 asitstands

The problem is NewType only has static support; at runtime there is no difference.

assert type(Int(0)) is int

So it's either support it as int, or not support it at all. Only a real type would distinguish the two.

class Int(int): ...

coady avatar Dec 05 '25 03:12 coady

Int = NewType('Int', int)
print(type(Int)) # <class 'typing.NewType'>
print(Int.__supertype__) # <class 'int'>

An instance of Int is actually an instance of int. However, the type Int itself is alive at runtime. What I'd like to do is something like

@multimethod
def foo(v: Int, t: type[Int]):
    # Some business logic

@multimethod
def foo(v: int, t: type[int]):
    # Some business logic

# These two behave differently
foo(1, Int)
foo(1, int)

Here the data 1 is actually int and multimethod also sees it as int, as far as I know. However, in my application, the data always has an attached type (Int) and needs to be handled differently according to the attached type. So, if multimethod can match Int with type[Int], the above code may work.

asitstands avatar Dec 06 '25 01:12 asitstands