Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is everything in Haskell stored in thunks, even simple values?

What do the thunks for the following value/expression/function look like in the Haskell heap?

val = 5                -- is `val` a pointer to a box containing 5? add x y = x + y         result = add 2 val      main = print $ result 

Would be nice to have a picture of how these are represented in Haskell, given its lazy evaluation mode.

like image 299
vis Avatar asked Dec 12 '11 17:12

vis


People also ask

What are thunks in Haskell?

A thunk is a value that is yet to be evaluated. It is used in Haskell systems that implement non-strict semantics by lazy evaluation. A lazy run-time system does not evaluate a thunk unless it has to.

Is Haskell lazy evaluation?

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.

Does Haskell support lazy processing?

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.

Why is lazy evaluation useful in Haskell?

Lazy evaluation is a method to evaluate a Haskell program. It means that expressions are not evaluated when they are bound to variables, but their evaluation is deferred until their results are needed by other computations.


2 Answers

Official answer

It's none of your business. Strictly implementation detail of your compiler.

Short answer

Yes.

Longer answer

To the Haskell program itself, the answer is always yes, but the compiler can and will do things differently if it finds out that it can get away with it, for performance reasons.

For example, for '''add x y = x + y''', a compiler might generate code that works with thunks for x and y and constructs a thunk as a result. But consider the following:

foo :: Int -> Int -> Int foo x y = x * x + y * y 

Here, an optimizing compiler will generate code that first takes x and y out of their boxes, then does all the arithmetic, and then stores the result in a box.

Advanced answer

This paper describes how GHC switched from one way of implementing thunks to another that was actually both simpler and faster: http://research.microsoft.com/en-us/um/people/simonpj/papers/eval-apply/

like image 106
wolfgang Avatar answered Sep 22 '22 06:09

wolfgang


In general, even primitive values in Haskell (e.g. of type Int and Float) are represented by thunks. This is indeed required by the non-strict semantics; consider the following fragment:

bottom :: Int bottom = div 1 0 

This definition will generate a div-by-zero exception only if the value of bottom is inspected, but not if the value is never used.

Consider now the add function:

add :: Int -> Int -> Int add x y = x+y 

A naive implementation of add must force the thunk for x, force the thunk for y, add the values and create an (evaluated) thunk for the result. This is a huge overhead for arithmetic compared to strict functional languages (not to mention imperative ones).

However, an optimizing compiler such as GHC can mostly avoid this overhead; this is a simplified view of how GHC translates the add function:

add :: Int -> Int -> Int add (I# x) (I# y) = case# (x +# y) of z -> I# z  

Internally, basic types like Int is seen as datatype with a single constructor. The type Int# is the "raw" machine type for integers and +# is the primitive addition on raw types. Operations on raw types are implemented directly on bit-patterns (e.g. registers) --- not thunks. Boxing and unboxing are then translated as constructor application and pattern matching.

The advantage of this approach (not visible in this simple example) is that the compiler is often capable of inlining such definitions and removing intermediate boxing/unboxing operations, leaving only the outermost ones.

like image 34
Pedro Avatar answered Sep 21 '22 06:09

Pedro