Skip to content

Instantly share code, notes, and snippets.

@serid
Created July 6, 2023 13:18
Show Gist options
  • Save serid/d655078bf2e3f3d7b524b37b084eafad to your computer and use it in GitHub Desktop.
Save serid/d655078bf2e3f3d7b524b37b084eafad to your computer and use it in GitHub Desktop.
class Lazy<T> {
f: () => T
value: T | null
constructor(f: () => T) {
this.f = f
this.value = null
}
get(): T {
if (this.value === null) {
this.value = this.f()
}
return this.value
}
static ofValue<T>(value: T): Lazy<T> {
return new Lazy(() => value)
}
}
class LateInit<T> {
value: T | null
constructor(value?: T) {
if (value === undefined)
this.value = null
else
this.value = value
}
get(): T {
if (this.value === null) {
throw new Error("value not set yet")
}
return this.value
}
set(value: T) {
if (this.value !== null) {
throw new Error("value already set")
}
this.value = value
}
}
function fixpoint<T>(foo: (self: Lazy<T>) => T): Lazy<T> {
let lateFoo = new LateInit<Lazy<T>>()
lateFoo.set(new Lazy(() => foo(lateFoo.get())))
return lateFoo.get()
}
function fixpoint2<A, B>(
f: (self1: Lazy<A>, self2: Lazy<B>) => A,
g: (self1: Lazy<A>, self2: Lazy<B>) => B
): [Lazy<A>, Lazy<B>] {
let lateF: LateInit<Lazy<A>> = new LateInit()
let lateG: LateInit<Lazy<B>> = new LateInit()
lateF.set(new Lazy(() => f(lateF.get(), lateG.get())))
lateG.set(new Lazy(() => g(lateF.get(), lateG.get())))
return [lateF.get(), lateG.get()]
}
// class List<T> {
// }
// class Cons<T> extends List<T> {
// head: T
// tail: Lazy<List<T>>
// constructor(head, tail) {
// super()
// this.head = head
// this.tail = tail
// }
// }
// class Nil<T> extends List<T> {
// }
// let oneTwos: Lazy<List<number>> = new Lazy(
// (self) => new Cons(1, Lazy.ofValue(new Cons (2, self)))
// )
// console.log((oneTwos.get() as Cons<number>).head);
// console.log(((oneTwos.get() as Cons<number>).tail.get() as Cons<number>).head);
// console.log((((oneTwos.get() as Cons<number>).tail.get() as Cons<number>).tail.get() as Cons<number>).head);
type Stream<T> = [T, Lazy<Stream<T>>]
let oneTwos: Lazy<Stream<number>> = fixpoint(
(self) => [1, Lazy.ofValue([2, self])]
)
console.log(oneTwos.get()[0])
console.log(oneTwos.get()[1].get()![0])
console.log(oneTwos.get()[1].get()![1].get()![0])
console.log()
let [threes, fours]: [Lazy<Stream<number>>, Lazy<Stream<number>>] = fixpoint2(
(self1, self2) => [3, self2],
(self1, self2) => [4, self1]
)
console.log(threes.get()[0])
console.log(threes.get()[1].get()![0])
console.log(threes.get()[1].get()![1].get()![0])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment