Skip to content

Instantly share code, notes, and snippets.

@cblp
Created September 28, 2022 20:59
Show Gist options
  • Save cblp/f7581a6b681e07ba27ca45f00c901c61 to your computer and use it in GitHub Desktop.
Save cblp/f7581a6b681e07ba27ca45f00c901c61 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
import operator
from typing import Callable, NamedTuple, Optional, TypeVar, Generic
A = TypeVar('A')
class Lazy(Generic[A]):
value: Optional[A]
# thunk: Callable[[], A]
def __init__(self, arg: A | Callable[[], A]):
assert arg is not None
if isinstance(arg, Lazy):
self.value = arg.value
if arg.value is None:
self.thunk = arg.thunk # type: ignore
elif callable(arg):
self.value = None
self.thunk = arg
else:
self.value = arg
def __call__(self) -> A:
if self.value is None:
self.value = self.thunk()
return self.value
def get(t: Callable[[], A] | Lazy[A]):
if callable(t):
return t()
else:
return t.get()
class Cons(NamedTuple):
head: int
tail: Lazy['Cons'] # type: ignore
def tail(xs: Lazy[Cons]) -> Callable[[], Cons]:
return lambda: xs().tail()
def zipWith(op: Callable[[int, int], int], xs: Lazy[Cons], ys: Lazy[Cons]) \
-> Cons:
x, xs = xs()
y, ys = ys()
return Cons(op(x, y), Lazy(lambda: zipWith(op, xs, ys)))
cons = lambda h, t: Lazy(Cons(h, Lazy(t)))
def main():
fibs: Lazy[Cons] = cons(
0,
cons(1, lambda: zipWith(operator.add, fibs, tail(fibs)))
)
it: Cons = fibs()
for i in range(100):
print(it.head)
it = it.tail()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment