Skip to content

Instantly share code, notes, and snippets.

@LeeeeT
Last active February 3, 2024 17:17
Show Gist options
  • Save LeeeeT/8c9a8bcef17a5705455de5dfc7743d97 to your computer and use it in GitHub Desktop.
Save LeeeeT/8c9a8bcef17a5705455de5dfc7743d97 to your computer and use it in GitHub Desktop.
I do not swear to God
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from typing import Final, NewType
class Compose[Value, Result]:
def __init__[Intermediate](self, second: Callable[[Intermediate], Result], first: Callable[[Value], Intermediate]) -> None:
self.second: Final = second
self.first: Final = first
def __call__(self, value: Value) -> Result:
return self.second(self.first(value))
@dataclass(frozen=True)
class Some[Value]:
value: Value
class Nothing:
pass
type Option[Value] = Nothing | Some[Value]
def option_join[Value](optional_option: Option[Option[Value]]) -> Option[Value]:
match optional_option:
case Nothing():
return Nothing()
case Some(option):
return option
@dataclass(frozen=True)
class OptionLift[Value, Result]:
function: Callable[[Value], Result]
def __call__(self, value: Value) -> Option[Result]:
return Some(self.function(value))
@dataclass(frozen=True)
class OptionMap[Value, Result]:
function: Callable[[Value], Result]
def __call__(self, option: Option[Value]) -> Option[Result]:
match option:
case Nothing():
return Nothing()
case Some(value):
return OptionLift(self.function)(value)
@dataclass(frozen=True)
class OptionBind[Value, Result]:
function: Callable[[Value], Option[Result]]
def __call__(self, option: Option[Value]) -> Option[Result]:
return option_join(OptionMap(self.function)(option))
class OptionCompose[Value, Result]:
def __init__[Intermediate](self, second: Callable[[Intermediate], Option[Result]], first: Callable[[Value], Option[Intermediate]]) -> None:
self.second: Final = second
self.first: Final = first
def __call__(self, value: Value) -> Option[Result]:
return OptionBind(self.second)(self.first(value))
class Valid:
pass
class Invalid:
pass
type ValidationResult = Valid | Invalid
type Validator[T] = Callable[[T], ValidationResult]
@dataclass(frozen=True)
class Greater:
compared: int
def __call__(self, value: int) -> 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()
Positive = NewType("Positive", int)
positive = Compose(OptionMap(Positive), AsParser(Greater(0)))
match positive(0):
case Nothing():
pass
case Some(value):
value: Positive = value
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment