# Lazy evaluation

Hi

as a follow-up to An endless list makes the REPL work for a long time and this is intentional (updated title), I was wondering if there is a way to make some computations explicitly lazy.

There are algorithms that can be expressed much more directly when using “infinite” structures. As a second example, a `find` follow by a `map` over a large list can become faster if the list the computation stops at the first element that matches the predicate.

Is there way to express such semantics in DAML?

Regards,
Alex

1 Like

There is no opt-in or explicit laziness or list fusion. So you have to manually merge the `map` with the `find`. In this case, the `findOptional` function in the standard library makes that relatively easy:

``````find p (map f xs)
``````

becomes

``````find (\x -> let y = f x in if p y then Some y else None) xs
``````
4 Likes

I’d also note that, while generalized laziness à la Haskell needs to be a language feature, building lazy lists as a library in an eager language is not difficult. If you really need to work with lazy lists a lot, you could build that yourself. Here is a minimal definition for `find p (map f xs)`:

``````
module Main where

import Daml.Script

data LazyList a = Nil | Cons {head: a, tail: () -> LazyList a}

(...) : a -> (() -> LazyList a) -> LazyList a
a ... f = Cons a f

lazy_map : (a -> b) -> LazyList a -> LazyList b
lazy_map f Nil = Nil
lazy_map f Cons{head, tail} = f head ... \() -> lazy_map f (tail ())

lazy_find : (a -> Bool) -> LazyList a -> Optional a
lazy_find p Nil = None

ints : LazyList Int
ints = 1 ... \() -> lazy_map (+1) ints

setup : Script ()
setup = script do
debug \$ lazy_find (> 5) ints
return ()
``````

There’s obviously going to be a performance overhead, so you should only do this if you really plan to have very long lists. This also doesn’t serialize (functions are not serializable), so you can’t put that into a template, but you can trivially convert back and forth:

``````to_lazy : [a] -> LazyList a
to_lazy [] = Nil
to_lazy (a::as) = a ... \() -> to_lazy as

from_lazy : LazyList a -> [a]
from_lazy Nil = []
and `lazy_find p (lazy_map f (to_lazy xs))` would give you the laziness you want here (i.e. `f` would only be called as many times as it takes to find the first match).