lean4-htt/tests/compile/lazylist.lean
Garmelon 08eb78a5b2
chore: switch to new test/bench suite (#12590)
This PR sets up the new integrated test/bench suite. It then migrates
all benchmarks and some related tests to the new suite. There's also
some documentation and some linting.

For now, a lot of the old tests are left alone so this PR doesn't become
even larger than it already is. Eventually, all tests should be migrated
to the new suite though so there isn't a confusing mix of two systems.
2026-02-25 13:51:53 +00:00

128 lines
3.9 KiB
Text
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
Copyright (c) 2019 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
-/
universe u v w
inductive LazyList (α : Type u) where
| nil : LazyList α
| cons (hd : α) (tl : LazyList α) : LazyList α
| delayed (t : Thunk $ LazyList α) : LazyList α
def List.toLazy {α : Type u} : List α → LazyList α
| [] => LazyList.nil
| h::t => LazyList.cons h (toLazy t)
namespace LazyList
variable {α : Type u} {β : Type v} {δ : Type w}
instance : Inhabited (LazyList α) :=
⟨nil⟩
@[inline] def pure : α → LazyList α
| a => cons a nil
partial def isEmpty : LazyList α → Bool
| nil => true
| cons _ _ => false
| delayed as => isEmpty as.get
partial def toList : LazyList α → List α
| nil => []
| cons a as => a :: toList as
| delayed as => toList as.get
partial def head [Inhabited α] : LazyList αα
| nil => default
| cons a as => a
| delayed as => head as.get
partial def tail : LazyList α → LazyList α
| nil => nil
| cons a as => as
| delayed as => tail as.get
partial def append : LazyList α → (Unit → LazyList α) → LazyList α
| nil, bs => bs ()
| cons a as, bs => delayed (cons a (append as bs))
| delayed as, bs => delayed (append as.get bs)
instance : Append (LazyList α) where
append a b := LazyList.append a (fun _ => b)
partial def interleave : LazyList α → LazyList α → LazyList α
| nil, bs => bs
| cons a as, bs => delayed (cons a (interleave bs as))
| delayed as, bs => delayed (interleave as.get bs)
partial def map (f : α → β) : LazyList α → LazyList β
| nil => nil
| cons a as => delayed (cons (f a) (map f as))
| delayed as => delayed (map f as.get)
partial def map₂ (f : α → β → δ) : LazyList α → LazyList β → LazyList δ
| nil, _ => nil
| _, nil => nil
| cons a as, cons b bs => delayed (cons (f a b) (map₂ f as bs))
| delayed as, bs => delayed (map₂ f as.get bs)
| as, delayed bs => delayed (map₂ f as bs.get)
@[inline] def zip : LazyList α → LazyList β → LazyList (α × β) :=
map₂ Prod.mk
partial def join : LazyList (LazyList α) → LazyList α
| nil => nil
| cons a as => delayed (append a fun _ => join as)
| delayed as => delayed (join as.get)
@[inline] partial def bind (x : LazyList α) (f : α → LazyList β) : LazyList β :=
join (x.map f)
instance isMonad : Monad LazyList where
pure := LazyList.pure
bind := LazyList.bind
map := LazyList.map
instance : Alternative LazyList where
failure := nil
orElse := LazyList.append
partial def approx : Nat → LazyList α → List α
| 0, as => []
| _, nil => []
| i+1, cons a as => a :: approx i as
| i+1, delayed as => approx (i+1) as.get
partial def iterate (f : αα) : α → LazyList α
| x => cons x (delayed (iterate f (f x)))
partial def iterate₂ (f : ααα) : αα → LazyList α
| x, y => cons x (delayed (iterate₂ f y (f x y)))
partial def filter (p : α → Bool) : LazyList α → LazyList α
| nil => nil
| cons a as => delayed (if p a then cons a (filter p as) else filter p as)
| delayed as => delayed (filter p as.get)
end LazyList
def fib : LazyList Nat :=
LazyList.iterate₂ (· + ·) 0 1
def iota (i : Nat := 0) : LazyList Nat :=
LazyList.iterate Nat.succ i
def tst : LazyList String := do
let x ← [1, 2, 3].toLazy
let y ← [2, 3, 4].toLazy
guard (x + y > 5)
pure s!"{x} + {y} = {x+y}"
def main : IO Unit := do
let n := 40
IO.println tst.isEmpty
IO.println tst.head
IO.println <| fib.interleave (iota.map (· + 100)) |>.approx n
IO.println <| iota.map (· + 10) |>.filter (· % 2 == 0) |>.approx n