Idris2/libs/contrib/Data/List/Lazy.idr
2020-09-19 22:48:45 +02:00

69 lines
1.6 KiB
Idris

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
(::) : a -> Lazy (LazyList a) -> LazyList a
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 |]
-- This function is unsafe because it asserts
-- that the seed gets smaller in every iteration
-- but the type system does not check that.
--
-- Use cautiously.
public export
unsafeUnfoldr : (b -> Maybe (a, b)) -> b -> LazyList a
unsafeUnfoldr next seed =
case next seed of
Nothing => []
Just (x, seed') =>
x :: Delay (unsafeUnfoldr next $ assert_smaller seed seed')