module Data.List.Lazy %default total -- All functions here are public export -- because their definitions are pretty much the specification. public export data LazyList : Type -> Type where Nil : LazyList a (::) : (1 x : a) -> (1 xs : Lazy (LazyList a)) -> LazyList a --- Interface implementations --- public export Semigroup (LazyList a) where [] <+> ys = ys (x :: xs) <+> ys = x :: (xs <+> ys) public export Monoid (LazyList a) where neutral = [] public export Foldable LazyList where foldr op nil [] = nil foldr op nil (x :: xs) = x `op` foldr op nil xs foldl op acc [] = acc foldl op acc (x :: xs) = foldl op (acc `op` x) xs public export Functor LazyList where map f [] = [] map f (x :: xs) = f x :: map f xs public export Applicative LazyList where pure x = [x] fs <*> vs = concatMap (\f => map f vs) fs public export Alternative LazyList where empty = [] (<|>) = (<+>) public export Monad LazyList where m >>= f = concatMap f m -- There is no Traversable instance for lazy lists. -- The result of a traversal will be a non-lazy list in general -- (you can't delay the "effect" of an applicative functor). public export traverse : Applicative f => (a -> f b) -> LazyList a -> f (List b) traverse g [] = pure [] traverse g (x :: xs) = [| g x :: traverse g xs |] public export sequence : Applicative f => LazyList (f a) -> f (List a) sequence = traverse id --- Lists creation --- public export fromList : List a -> LazyList a fromList [] = [] fromList (x::xs) = x :: fromList xs covering public export iterate : (f : a -> Maybe a) -> (x : a) -> LazyList a iterate f x = x :: case f x of Nothing => [] Just y => iterate f y public export iterateN : Nat -> (a -> a) -> a -> LazyList a iterateN Z _ _ = [] iterateN (S n) f x = x :: iterateN n f (f x) public export replicate : (n : Nat) -> (x : a) -> LazyList a replicate Z _ = [] replicate (S n) x = x :: replicate n x --- Functions for acquiring different types of sublists --- public export take : Nat -> LazyList a -> LazyList a take (S k) (x::xs) = x :: take k xs take _ _ = [] public export drop : Nat -> LazyList a -> LazyList a drop Z xs = xs drop (S _) [] = [] drop (S n) (_::xs) = drop n xs public export takeWhile : (a -> Bool) -> LazyList a -> LazyList a takeWhile p [] = [] takeWhile p (x::xs) = if p x then x :: takeWhile p xs else [] public export dropWhile : (a -> Bool) -> LazyList a -> LazyList a dropWhile p [] = [] dropWhile p (x::xs) = if p x then dropWhile p xs else x::xs public export filter : (a -> Bool) -> LazyList a -> LazyList a filter p [] = [] filter p (x::xs) = if p x then x :: filter p xs else filter p xs