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 <| List.range 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 <| List.range 1 1000000)
sums : ( Int, Int, Int )
sums =
( force lazySum, force lazySum, force lazySum )Evaluate the lazy value if it has not already been evaluated. If it has, do nothing.
lazySum : Lazy Int
lazySum =
lazy (() -> List.sum <| List.range 1 1000000)
sums : ( Int, Int, Int )
sums =
let
evaledSum =
evaluate lazySum
in
( force evaledSum, force evaledSum, force evaledSum )This is mainly useful for cases where you may want to store a lazy value as a
lazy value and pass it around. For example, in a list. Where possible, it is better to use
force and simply store the computed value separately.
Lazily apply a function to a lazy value.
lazySum : Lazy Int
lazySum =
map List.sum (lazy (() -> List.range 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 <| List.range 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 : (a -> b -> c -> result) -> Lazy a -> Lazy b -> Lazy c -> Lazy result
map3 f a b c =
apply (apply (apply (lazy (\() -> f)) a) b) cIt is not the most beautiful, but it is equivalent and will let you create
map9 quite easily if you really need it.
Piping-friendly version of apply.
map3 : (a -> b -> c -> result) -> Lazy a -> Lazy b -> Lazy c -> Lazy result
map3 f a b c =
lazy (\() -> f) |> andMap a |> andMap b |> andMap cLazily chain lazy computations together, 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.