module PrettyLazyList where
import Lazy exposing (Lazy, lazy, force)
type LazyList a
= Nil
| Cons a (Lazy (LazyList a))
head : LazyList a -> a
head l = case l of Cons x _ -> x
Nil -> Debug.crash "head"
tail : LazyList a -> LazyList a
tail l = case l of Cons _ xs -> force xs
Nil -> Debug.crash "tail"
range : Int -> Int -> LazyList Int
range i j =
if i > j
then Nil
else Cons i (lazy (\() -> range (i+1) j))
infinite : Int -> LazyList Int
infinite i = Cons i (lazy (\_ -> infinite (i+1)))
take : Int -> LazyList a -> LazyList a
take k l = case (k, l) of
(0, _) -> Nil
(_, Nil) -> Nil
(_, Cons x xs) -> Cons x (lazy (\() -> take (k-1) (force xs)))
drop : Int -> LazyList a -> LazyList a
drop k l = case (k, l) of
(0, _) -> l
(_, Nil) -> Nil
(_, Cons _ xs) -> drop (k-1) (force xs)
append : LazyList a -> LazyList a -> LazyList a
append xs ys = case xs of
Nil -> ys
Cons x xs' -> Cons x (lazy (\_ -> append (force xs') ys))
reverse : LazyList a -> LazyList a
reverse l =
let foo acc xs = case xs of
Nil -> acc
Cons x xs' -> foo (Cons x (lazy (\_ -> acc))) (force xs')
in foo Nil l
toList : LazyList a -> List a
toList l =
let foo acc l = case l of
Nil -> acc
Cons x xs -> foo (x::acc) (force xs)
in
List.reverse <| foo [] l
eq : LazyList a -> LazyList a -> Bool
eq x y =
let foo x y = case (x, y) of
(Cons x xs, Cons y ys) ->
if x == y
then foo (force xs) (force ys)
else False
(Nil, Nil) -> True
_ -> False
in
foo x y