I need some clarification about laziness with Haskell.
If I have this function:
myFunction arg | arg == 1 = a | arg == 2 = a*b | arg == 3 = b+c | otherwise = (a+b)*c where a = ... b = ... c = ... d = ...
When I call myFunction 1
, Haskell will evaluate only the a = ...
function, neither b nor c, nor d.
But if I write
myFunction arg | arg == 1 = a | arg == 2 = a*b | arg == 3 = b+c | otherwise = (a+b)*c where (a,b,c,d) = anotherFunction arg
What will Haskell's behaviour be?
anotherFunction
?anotherFunction
?Haskell is a lazy language, meaning that it employs lazy evaluation . Before explaining lazy evaluation , let's first explain strict evaluation which most readers will likely be more familiar with. Strict evaluation means that arguments to functions are evaluated prior to being passed to the functions.
Haskell is often described as a lazy language.
Haskell is a lazy language. It does not evaluate expressions until it absolutely must. This frequently allows our programs to save time by avoiding unnecessary computation, but they are at more of a risk to leak memory. There are ways of introducing strictness into our programs when we don't want lazy evaluation.
Haskell uses a special form of evaluation called lazy evaluation. In lazy evaluation, no code is evaluated until it's needed. In the case of longList , none of the values in the list were needed for computation.
In both cases, it won't evaluate anything unless the value is demanded. One way of demanding the value is calling the function in ghci (which prints the value in ghci
and hence demanding it). Assuming that you are executing the function, then in your second case it will evaluate the tuple to weak head normal form (WHNF) and then evaluate the first element in (a,b,c,d)
because only that value is demanded. The other elements b
, c
and d
will be in the thunk form. In fact you can verify that yourself:
myFunction arg | arg == 1 = a | arg == 2 = a*b | arg == 3 = b+c | otherwise = (a+b)*c where (a,b,c,d) = anotherFunction arg anotherFunction x = (x, undefined, undefined, undefined)
Demo in ghci:
λ> myFunction 1 1
Well it is only interested in a
, so that means that there is an implicit function:
thea :: (a,b,c,d) -> a thea (a,_,_,_) = a
In other words Haskell is not interested in the other elements of the tuple. Sometimes however the elements of the tuple share some structure. Say another function is defined as:
anotherFunction :: Int -> (Int,Int,Int,Int) anotherFunction x = (z,t,f,g) where f = x*x g = f+x z = g-2 t = 3
In that case - in order to evaluate the first element - the third and fourth element will also be evaluated. But since you don't do anything with them, Haskell won't be interested in their result specifically.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With