This library lets you delay a computation until later.
Delay the evaluation of a value until later. For example, maybe we will need to generate a very long list and find its sum, but we do not want to do it unless it is absolutely necessary.
lazySum : Lazy Int
lazySum =
lazy (\() -> sum [1..1000000])Now we only pay for lazySum if we actually need it.
Force the evaluation of a lazy value. This means we only pay for the computation when we need it. Here is a rather contrived example.
lazySum : Lazy Int
lazySum =
lazy (\() -> List.sum [1..1000000])
sums : (Int, Int, Int)
sums =
(force lazySum, force lazySum, force lazySum)We are forcing this computation three times. The cool thing is that the first
time you force a value, the result is stored. This means you pay the cost on
the first one, but all the rest are very cheap, basically just looking up a
value in memory.
Lazily apply a function to a lazy value.
lazySum : Lazy Int
lazySum =
map List.sum (lazy (\() -> [1..1000000]))The resulting lazy value will create a big list and sum it up when it is finally forced.
Lazily apply a function to two lazy values.
lazySum : Lazy Int
lazySum =
lazy (\() -> List.sum [1..1000000])
lazySumPair : Lazy (Int, Int)
lazySumPair =
map2 (,) lazySum lazySumLazily apply a lazy function to a lazy value. This is pretty rare on its own, but it lets you map as high as you want.
map3 f a b == f `map` a `apply` b `apply` cIt is not the most beautiful, but it is equivalent and will let you create
map9 quite easily if you really need it.
Lazily chain together lazy computations, for when you have a series of steps that all need to be performed lazily. This can be nice when you need to pattern match on a value, for example, when appending lazy lists:
type List a = Empty | Node a (Lazy (List a))
cons : a -> Lazy (List a) -> Lazy (List a)
cons first rest =
Lazy.map (Node first) rest
append : Lazy (List a) -> Lazy (List a) -> Lazy (List a)
append lazyList1 lazyList2 =
let
appendHelp list1 =
case list1 of
Empty ->
lazyList2
Node first rest ->
cons first (append rest list2))
in
lazyList1
|> Lazy.andThen appendHelpBy using andThen we ensure that neither lazyList1 or lazyList2 are forced
before they are needed. So as written, the append function delays the pattern
matching until later.
A wrapper around a value that will be lazily evaluated.