Skip to content

Instantly share code, notes, and snippets.

@LeeeeT
Last active February 1, 2024 02:26
Show Gist options
  • Save LeeeeT/6e6b4c5eb578cf2797ae4133d06ea23c to your computer and use it in GitHub Desktop.
Save LeeeeT/6e6b4c5eb578cf2797ae4133d06ea23c to your computer and use it in GitHub Desktop.
I swear to God
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from typing import cast, Final, NewType
class Compose[A, C]:
def __init__[B](self, f: Callable[[B], C], g: Callable[[A], B]) -> None:
self.f: Final = f
self.g: Final = g
def __call__(self, value: A) -> C:
return self.f(self.g(value))
@dataclass(frozen=True)
class Some[T]:
value: T
class Nothing:
pass
type Option[T] = Nothing | Some[T]
def option_join[T](value: Option[Option[T]]) -> Option[T]:
match value:
case Nothing():
return Nothing()
case Some(v):
return v
@dataclass(frozen=True)
class OptionLift[T, F]:
f: Callable[[T], F]
def __call__(self, value: T) -> Option[F]:
return Compose(Some, self.f)(value)
@dataclass(frozen=True)
class OptionMap[T, F]:
f: Callable[[T], F]
def __call__(self, value: Option[T]) -> Option[F]:
match value:
case Nothing():
return Nothing()
case Some(v):
return OptionLift(self.f)(v)
@dataclass(frozen=True)
class OptionBind[T, F]:
f: Callable[[T], Option[F]]
def __call__(self, value: Option[T]) -> Option[F]:
return option_join(OptionMap(self.f)(value))
class OptionCompose[A, C]:
def __init__[B](self, f: Callable[[B], Option[C]], g: Callable[[A], Option[B]]) -> None:
self.f: Final = f
self.g: Final = g
def __call__(self, value: A) -> Option[C]:
return OptionBind(self.f)(self.g(value))
class Valid:
pass
class Invalid:
pass
type ValidationResult = Valid | Invalid
type Validator[T] = Callable[[T], ValidationResult]
@dataclass(frozen=True)
class Greater:
compared: float
def __call__(self, value: float) -> ValidationResult:
return Valid() if value > self.compared else Invalid()
@dataclass(frozen=True)
class AsParser[T]:
validator: Validator[T]
def __call__(self, value: T) -> Option[T]:
match self.validator(value):
case Valid():
return Some(value)
case Invalid():
return Nothing()
class Its[T]:
pass
@dataclass(frozen=True)
class ISwearToGod[T]:
its: type[Its[T]]
def __call__(self, value: object) -> T:
return cast(T, value)
_Positive = NewType("_Positive", int)
type Positive = _Positive
validator = Greater(0)
swear = ISwearToGod(Its[Positive])
positive = OptionCompose(OptionLift(swear), AsParser(validator))
match positive(0):
case Nothing():
pass
case Some(v):
v: Positive = v
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment