Last active
February 7, 2024 19:25
-
-
Save LeeeeT/8e44c2f81b69665f43cf02481fdabe8a to your computer and use it in GitHub Desktop.
Order
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 collections.abc import Callable | |
from dataclasses import dataclass | |
from typing import Concatenate | |
@dataclass(frozen=True) | |
class Partial1[First, **Rest, Result]: | |
function: Callable[Concatenate[First, Rest], Result] | |
first: First | |
def __call__(self, *args: Rest.args, **kwargs: Rest.kwargs) -> Result: | |
return self.function(self.first, *args, **kwargs) | |
@dataclass(frozen=True) | |
class Partial2[First, Second, **Rest, Result]: | |
function: Callable[Concatenate[First, Second, Rest], Result] | |
first: First | |
second: Second | |
def __call__(self, *args: Rest.args, **kwargs: Rest.kwargs) -> Result: | |
return self.function(self.first, self.second, *args, **kwargs) | |
@dataclass(frozen=True) | |
class Curry1[First, **Rest, Result]: | |
function: Callable[Concatenate[First, Rest], Result] | |
def __call__(self, first: First) -> Callable[Rest, Result]: | |
return Partial1(self.function, first) | |
@dataclass(frozen=True) | |
class Curry2[First, Second, **Rest, Result]: | |
function: Callable[Concatenate[First, Second, Rest], Result] | |
def __call__(self, first: First, second: Second) -> Callable[Rest, Result]: | |
return Partial2(self.function, first, second) | |
@dataclass(frozen=True) | |
class Uncurry1[First, **Rest, Result]: | |
function: Callable[[First], Callable[Rest, Result]] | |
def __call__(self, first: First, *args: Rest.args, **kwargs: Rest.kwargs) -> Result: | |
return self.function(first)(*args, **kwargs) | |
@dataclass(frozen=True) | |
class Uncurry2[First, Second, **Rest, Result]: | |
function: Callable[[First], Callable[[Second], Callable[Rest, Result]]] | |
def __call__(self, first: First, second: Second, *args: Rest.args, **kwargs: Rest.kwargs) -> Result: | |
return self.function(first)(second)(*args, **kwargs) | |
type Predicate[Value] = Callable[[Value], bool] | |
def predicate_both[Value](second: Predicate[Value], first: Predicate[Value], value: Value) -> bool: | |
return first(value) and second(value) | |
def make_predicate_both[Value](second: Predicate[Value], first: Predicate[Value]) -> Predicate[Value]: | |
return Partial2(predicate_both, second, first) | |
def predicate_either[Value](second: Predicate[Value], first: Predicate[Value], value: Value) -> bool: | |
return first(value) or second(value) | |
def make_predicate_either[Value](second: Predicate[Value], first: Predicate[Value]) -> Predicate[Value]: | |
return Partial2(predicate_either, second, first) | |
def predicate_not[Value](predicate: Predicate[Value], value: Value) -> bool: | |
return not predicate(value) | |
def make_predicate_not[Value](predicate: Predicate[Value]) -> Predicate[Value]: | |
return Partial1(predicate_not, predicate) | |
class OrderingLess: | |
pass | |
class OrderingEqual: | |
pass | |
class OrderingGreater: | |
pass | |
type Ordering = OrderingLess | OrderingEqual | OrderingGreater | |
def ordering_equal(a: Ordering, b: Ordering) -> bool: | |
match a, b: | |
case OrderingLess(), OrderingLess(): | |
return True | |
case OrderingEqual(), OrderingEqual(): | |
return True | |
case OrderingGreater(), OrderingGreater(): | |
return True | |
case _: | |
return False | |
def make_ordering_equal(a: Ordering) -> Predicate[Ordering]: | |
return Partial1(ordering_equal, a) | |
is_ordering_less = make_ordering_equal(OrderingLess()) | |
is_ordering_equal = make_ordering_equal(OrderingEqual()) | |
is_ordering_greater = make_ordering_equal(OrderingGreater()) | |
is_ordering_less_or_equal = make_predicate_either(is_ordering_less, is_ordering_equal) | |
is_ordering_greater_or_equal = make_predicate_either(is_ordering_greater, is_ordering_equal) | |
is_ordering_different = make_predicate_not(is_ordering_equal) | |
type Order[Value] = Callable[[Value, Value], Ordering] | |
def order_predicate[Value](predicate: Predicate[Ordering], order: Order[Value], a: Value, b: Value) -> bool: | |
return predicate(order(a, b)) | |
def make_order_predicate[Value](predicate: Predicate[Ordering], order: Order[Value]) -> Callable[[Value, Value], bool]: | |
return Partial2(order_predicate, predicate, order) | |
def make_make_order_predicate[Value](predicate: Predicate[Ordering]) -> Callable[[Order[Value]], Callable[[Value, Value], bool]]: | |
return Partial1(make_order_predicate, predicate) | |
make_less = make_make_order_predicate(is_ordering_less) | |
make_equal = make_make_order_predicate(is_ordering_equal) | |
make_greater = make_make_order_predicate(is_ordering_greater) | |
make_less_or_equal = make_make_order_predicate(is_ordering_less_or_equal) | |
make_greater_or_equal = make_make_order_predicate(is_ordering_greater_or_equal) | |
make_different = make_make_order_predicate(is_ordering_different) | |
def make_range[Value](make_lower_bound_predicate: Callable[[Value], Predicate[Value]], make_upper_bound_predicate: Callable[[Value], Predicate[Value]], minimum: Value, maximum: Value) -> Predicate[Value]: | |
return make_predicate_both(make_lower_bound_predicate(minimum), make_upper_bound_predicate(maximum)) | |
def make_make_range[Value](make_lower_bound_predicate: Callable[[Value], Predicate[Value]], make_upper_bound_predicate: Callable[[Value], Predicate[Value]]) -> Callable[[Value, Value], Predicate[Value]]: | |
return Partial2(make_range, make_lower_bound_predicate, make_upper_bound_predicate) | |
def int_order(a: int, b: int) -> Ordering: | |
if a > b: | |
return OrderingLess() | |
if a < b: | |
return OrderingGreater() | |
return OrderingEqual() | |
int_less = make_less(int_order) | |
def make_int_less(compared: int) -> Predicate[int]: | |
return Partial1(int_less, compared) | |
int_equal = make_equal(int_order) | |
def make_int_equal(compared: int) -> Predicate[int]: | |
return Partial1(int_equal, compared) | |
int_greater = make_greater(int_order) | |
def make_int_greater(compared: int) -> Predicate[int]: | |
return Partial1(int_greater, compared) | |
int_less_or_equal = make_less_or_equal(int_order) | |
def make_int_less_or_equal(compared: int) -> Predicate[int]: | |
return Partial1(int_less_or_equal, compared) | |
int_greater_or_equal = make_greater_or_equal(int_order) | |
def make_int_greater_or_equal(compared: int) -> Predicate[int]: | |
return Partial1(int_greater_or_equal, compared) | |
int_different = make_different(int_order) | |
def make_int_different(compared: int) -> Predicate[int]: | |
return Partial1(int_different, compared) | |
int_inclusive_inclusive = make_make_range(make_int_greater_or_equal, make_int_less_or_equal) | |
int_inclusive_exclusive = make_make_range(make_int_greater_or_equal, make_int_less) | |
int_exclusive_inclusive = make_make_range(make_int_greater, make_int_less_or_equal) | |
int_exclusive_exclusive = make_make_range(make_int_greater, make_int_less) | |
between_1_and_10 = int_inclusive_inclusive(1, 10) | |
match between_1_and_10(int(input())): | |
case True: | |
print("Yay!") | |
case False: | |
print("Oh..") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment