Created
February 24, 2024 11:43
-
-
Save LeeeeT/3600fa17bf98af991cf9b28173b25774 to your computer and use it in GitHub Desktop.
Laziness complete
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 collections.abc import Callable, Iterator | |
from typing import Protocol, cast | |
type Lazy[Value] = Callable[[], Value] | |
def lazify[Value](value: Value) -> Lazy[Value]: | |
return lambda: value | |
class Option[Value](Protocol): | |
def __call__[Return](self, nothing_case: Lazy[Return], some_case: Lazy[Callable[[Lazy[Value]], Lazy[Return]]]) -> Lazy[Return]: | |
... | |
@lazify | |
def nothing[Value, Return](nothing_case: Lazy[Return], some_case: Lazy[Callable[[Lazy[Value]], Lazy[Return]]]) -> Lazy[Return]: | |
return nothing_case | |
@lazify | |
def some[Value](value: Lazy[Value]) -> Lazy[Option[Value]]: | |
@lazify | |
def option[Return](nothing_case: Lazy[Return], some_case: Lazy[Callable[[Lazy[Value]], Lazy[Return]]]) -> Lazy[Return]: | |
return lambda: some_case()(value)() | |
return option | |
class Natural(Protocol): | |
def __call__[Return](self, zero_case: Lazy[Return], successor_case: Lazy[Callable[[Lazy[Natural]], Lazy[Return]]]) -> Lazy[Return]: | |
... | |
@cast(Callable[[Natural], Lazy[Natural]], lazify) | |
def zero[Return](zero_case: Lazy[Return], successor_case: Lazy[Callable[[Lazy[Natural]], Lazy[Return]]]) -> Lazy[Return]: | |
return zero_case | |
@lazify | |
def successor(number: Lazy[Natural]) -> Lazy[Natural]: | |
@lazify | |
def successor[Return](zero_case: Lazy[Return], successor_case: Lazy[Callable[[Lazy[Natural]], Lazy[Return]]]) -> Lazy[Return]: | |
return lambda: successor_case()(number)() | |
return successor | |
one = successor()(zero) | |
two = successor()(one) | |
three = successor()(two) | |
@lazify | |
def int_to_natural(int: Lazy[int]) -> Lazy[Natural]: | |
return lambda: successor()(lambda: int_to_natural()(lambda: int() - 1)())() if int() else zero() | |
@lazify | |
def natural_to_int(natural: Lazy[Natural]) -> Lazy[int]: | |
@lazify | |
def natural_successor_case(natural_predessor: Lazy[Natural]) -> Lazy[int]: | |
return lambda: natural_to_int()(natural_predessor)() + 1 | |
return lambda: natural()(lambda: 0, natural_successor_case)() | |
class Stream[Value](Protocol): | |
def __call__[Return](self, consumer: Lazy[Callable[[Lazy[Value], Lazy[Stream[Value]]], Lazy[Return]]]) -> Lazy[Return]: | |
... | |
@lazify | |
def stream_of[Value](value: Lazy[Value]) -> Lazy[Stream[Value]]: | |
@lazify | |
def stream[Return](consumer: Lazy[Callable[[Lazy[Value], Lazy[Stream[Value]]], Lazy[Return]]]) -> Lazy[Return]: | |
return lambda: consumer()(value, lambda: stream_of()(value)())() | |
return stream | |
class List[Value](Protocol): | |
def __call__[Return](self, empty_case: Lazy[Return], constructor_case: Lazy[Callable[[Lazy[Value], Lazy[List[Value]]], Lazy[Return]]]) -> Lazy[Return]: | |
... | |
@lazify | |
def empty[Value, Return](empty_case: Lazy[Return], constructor_case: Lazy[Callable[[Lazy[Value], Lazy[List[Value]]], Lazy[Return]]]) -> Lazy[Return]: | |
return empty_case | |
@lazify | |
def constructor[Value](head: Lazy[Value], tail: Lazy[List[Value]]) -> Lazy[List[Value]]: | |
@lazify | |
def list[Return](empty_case: Lazy[Return], constructor_case: Lazy[Callable[[Lazy[Value], Lazy[List[Value]]], Lazy[Return]]]) -> Lazy[Return]: | |
return lambda: constructor_case()(head, tail)() | |
return list | |
@lazify | |
def take[Value](number: Lazy[Natural], stream: Lazy[Stream[Value]]) -> Lazy[List[Value]]: | |
@lazify | |
def number_successor_case(number_predessor: Lazy[Natural]) -> Lazy[List[Value]]: | |
@lazify | |
def consumer(head: Lazy[Value], tail: Lazy[Stream[Value]]) -> Lazy[List[Value]]: | |
return lambda: constructor()(head, lambda: take()(number_predessor, tail)())() | |
return lambda: stream()(consumer)() | |
return lambda: number()(empty, number_successor_case)() | |
@lazify | |
def stream_to_list[Value](stream: Lazy[Stream[Value]]) -> Lazy[List[Value]]: | |
@lazify | |
def consumer(head: Lazy[Value], tail: Lazy[Stream[Value]]) -> Lazy[List[Value]]: | |
return lambda: constructor()(head, lambda: stream_to_list()(tail)())() | |
return lambda: stream()(consumer)() | |
@lazify | |
def safe_next[Value](iterator: Lazy[Iterator[Lazy[Value]]]) -> Lazy[Option[Value]]: | |
def option() -> Option[Value]: | |
try: | |
return some()(next(iterator()))() | |
except StopIteration: | |
return nothing() | |
return option | |
@lazify | |
def iterator_to_list[Value](iterator: Lazy[Iterator[Lazy[Value]]]) -> Lazy[List[Value]]: | |
@lazify | |
def safe_next_some_case(value: Lazy[Value]) -> Lazy[List[Value]]: | |
return lambda: constructor()(value, lambda: iterator_to_list()(iterator)())() | |
return lambda: safe_next()(iterator)()(empty, safe_next_some_case)() | |
@lazify | |
def list_to_iterator[Value](list: Lazy[List[Value]]) -> Lazy[Iterator[Lazy[Value]]]: | |
@lazify | |
def list_constructor_case(head: Lazy[Value], tail: Lazy[List[Value]]) -> Lazy[Iterator[Lazy[Value]]]: | |
def iterator() -> Iterator[Lazy[Value]]: | |
yield head | |
yield from list_to_iterator()(tail)() | |
return iterator | |
return lambda: list()(lambda: iter(()), list_constructor_case)() | |
stream_of_ones = stream_of()(one) | |
three_ones = take()(three, stream_of_ones) | |
for n in list_to_iterator()(three_ones)(): | |
print(natural_to_int()(n)()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment