Last active
July 1, 2021 12:24
-
-
Save edelooff/02050858d72a3dad6c0031db08ce5ae8 to your computer and use it in GitHub Desktop.
Playing with structural typing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import annotations | |
from dataclasses import dataclass | |
from typing import Generic, Optional, Protocol, TypeVar | |
CT = TypeVar("CT", bound="Comparable") | |
class Comparable(Protocol): | |
def __lt__(self: CT, other: CT) -> bool: | |
... | |
class NodeProto(Protocol[CT]): | |
value: CT | |
@property | |
def left(self) -> Optional[NodeProto[CT]]: | |
... | |
@property | |
def right(self) -> Optional[NodeProto[CT]]: | |
... | |
Node = NodeProto[Comparable] | |
@dataclass | |
class BinaryNode(Generic[CT]): | |
value: CT | |
left: Optional[BinaryNode[CT]] = None | |
right: Optional[BinaryNode[CT]] = None | |
@dataclass | |
class BN2(Generic[CT]): | |
value: CT | |
left: Optional[BN2[CT]] = None | |
right: Optional[BN2[CT]] = None | |
def main() -> None: | |
n1: NodeProto = BinaryNode("foo") | |
# error: Missing type parameters for generic type "NodeProto" | |
# caused by making Protocol generic over CT | |
n1b: Node = BinaryNode("foo") # Node is an alias for NodeProto[Comparable] | |
n2 = BinaryNode("foo") # n2 has type BinaryNode[str] | |
n2.left = BinaryNode(1) | |
# error: Argument 1 to "BinaryNode" has incompatible type "int"; expected "str" | |
# caught by making Protocol generic over CT | |
n3 = BinaryNode(object()) | |
# error: Value of type variable "CT" of "BinaryNode" cannot be "object" | |
n4: BinaryNode[Comparable] = BinaryNode("stringtyped") | |
n4.left = BinaryNode(2) # allowed: both types are comparable, even if different :( | |
n4.right = BinaryNode(object()) | |
# error: Argument 1 to "BinaryNode" has incompatible type "object"; | |
# expected "Comparable" | |
n5 = BinaryNode(5) | |
n5.left = BinaryNode(3) | |
n5.right = BN2(7) | |
# error: Incompatible types in assignment (expression has type "BN2[int]", | |
# variable has type "Optional[BinaryNode[int]]") | |
n6: BinaryNode[object] | |
# error: Type argument "builtins.object" of "BinaryNode" | |
# must be a subtype of "trees.Comparable" | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment