Resolve an ambiguous rule¤
You called a quaxified function and plum could not decide which of your rules to use:
AmbiguousLookupError: `mul_dispatcher(Meters(array=f32[3]), Meters(array=f32[3]))`
is ambiguous.
Two rules match the call and neither is more specific than the other. The usual shape is a pair written for mixed operands, meeting a call where both operands are yours:
import equinox as eqx
import jax
import jax.numpy as jnp
import quax
from jaxtyping import ArrayLike
from typing import Any
class Meters(quax.ArrayValue):
array: jax.Array = eqx.field(converter=jnp.asarray)
def materialise(self):
return self.array
def aval(self):
return jax.typeof(self.array)
@quax.register(jax.lax.mul_p)
def mul_meters_any(x: Meters, y: Meters | ArrayLike, **kw: Any) -> Meters:
return Meters(jax.lax.mul_p.bind(x.array, getattr(y, "array", y), **kw))
@quax.register(jax.lax.mul_p)
def mul_any_meters(x: Meters | ArrayLike, y: Meters, **kw: Any) -> Meters:
return Meters(jax.lax.mul_p.bind(getattr(x, "array", x), y.array, **kw))
Meters * Meters matches both, equally well.
If you own both rules¤
Add the specific rule and give it a higher precedence. Dispatch then has a single best answer rather than a tie:
@quax.register(jax.lax.mul_p, precedence=1)
def mul_meters_meters(x: Meters, y: Meters, **kw: Any) -> Meters:
return Meters(jax.lax.mul_p.bind(x.array, y.array, **kw))
out = quax.quaxify(lambda a, b: a * b)(Meters(jnp.full(3, 2.0)), Meters(jnp.full(3, 3.0)))
print(out.array) # [6. 6. 6.]
Write the rule you actually want for that combination — the precedence only breaks the tie, it does not choose behaviour for you.
If the clash is between two libraries¤
Do not register a rule for the combination. You would be deciding, on behalf of two projects you do not own, what their types mean together — and the answer would apply process-wide to everyone who imports you.
Reach for nested quaxifies instead: quaxify the
outer call for one type, and let the other reach its own quax.quaxify further
in.
See also¤
The advanced tutorial works through why the ambiguity arises, if you want the reasoning rather than the fix.