Services: tags, references, and the context that holds them.
A tag names a service. Its identity is the class, and its type parameter is the service's shape, so two tags can share a shape and stay distinct::
class Database(Protocol):
def find(self, key: str) -> str | None: ...
class Primary(Tag[Database]): ...
class Replica(Tag[Database]): ...
def program():
db = yield from Primary() # Database; adds Primary to RCalling a tag class does not construct anything: it gives the effect that reads the service from the running fiber's context.
A Reference is a tag with a default value. Effects that read a
reference do not need it provided, so it never appears in R::
class LogLevel(Reference[int]):
@classmethod
def default(cls) -> int:
return 20| Attribute | Type | Description |
|---|---|---|
S_inv | = TypeVar('S_inv') | |
T_co | = TypeVar('T_co', covariant=True) | |
R_contra | = TypeVar('R_contra', contravariant=True, default=Any) |
Classes#
Functions#
tag_class#
tag_class(tag) -> type[Tag[S]]The class behind a TagLike. Every TagLike is a tag class;
the protocol only exists so signatures can name its shape and tag.
| Parameter | Type | Description |
|---|---|---|
tag | TagLike[S, T] |
Returns type[Tag[S]]
def tag_class[S, T](tag: TagLike[S, T]) -> type[Tag[S]]:
"""The class behind a ``TagLike``. Every ``TagLike`` is a tag class;
the protocol only exists so signatures can name its shape and tag."""
if isinstance(tag, type) and issubclass(tag, Tag):
return tag # pyright: ignore[reportUnknownVariableType]
raise TypeError(f"{tag!r} is not a Tag class")