Proposal: Trait for strict, non-widening type bounds (solving LSP issues in binary ops)
#2143
kamalfarahani
started this conversation in
General
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Abstract
I propose introducing a new construct named
Trait. Unlike anABCorProtocol, aTraitacts as a strict constraint that prevents the type solver from "widening" aTypeVarto the base type. This specifically solves the long-standing issue of defining binary operations (like Semigroups) on subclasses without violating the Liskov Substitution Principle (LSP).The Problem: The "Binary Operation" Paradox
In current Python typing, if we want to define a generic binary operation, we often run into a conflict between type safety and LSP.
Why this fails today:
combineis called with anIntand aString, the type checker sees both satisfySemigroup. It resolvesTtoSemigroup.Semigroup.opmust accept any otherSemigroup. But for concrete logic (like addition), it must only accept its own type.The Solution:
TraitIf we define
Semigroupas aTrait, we change the rules of engagement. ATraitis not a "parent type" that objects can be widened to; it is a requirement that a concrete type must satisfy.Why this is better
Semigroupis aTraitand not a base class, we are not saying "Int is a Semigroup" in a way that requires substitution. We are saying "Int implements the Semigroup interface."TypeError: The type checker catches "mixed implementation" calls that currently pass when usingABCbounds.Proposed Semantics
Trait, and aTypeVarbound by aTraitcannot resolve to thatTrait.TypeVaris bound by aTrait, all arguments associated with thatTypeVarmust unify to the exact same concrete type.Beta Was this translation helpful? Give feedback.
All reactions