What is the relationship between unrelated types and stringency?

Unboxed types like Int# and strict functions like f (!x) = ... are somewhat different, but I see a conceptual similarity - they somehow prohibit tricks / laziness. If Haskell was a strict language like Ocaml, every function would be strict, and every type would be unpacked. What is the relationship between unrelated types and strictness?

+22
haskell lazy-evaluation evaluation strictness
Jun 28 '10 at 10:18
source share
3 answers

Unboxed vs Boxed Data strong>

To support parametric polymorphism and laziness , by default, Haskell data types are represented uniformly as a pointer to closure on the heap , with a structure like this:

alt text

These are boxed values. An unboxed object is represented directly by the value itself without any indirect restrictions or closures. Int is put into the box, but Int# unpacked.

Lazy values ​​require a boxed representation. They do not have strict values: they can be represented either as fully evaluated closures in the heap, or as primitive unpacked structures. Note that the tag pointer is an optimization that we can use on box objects to encode the constructor in the close pointer.

Severity

Usually unoccupied values ​​are generated in a special way by functional language compilers. In Haskell, however, unboxed values are special. They:

  • they have a different type, # ;
  • can only be used in special places; and
  • they are not used, therefore they are not presented as a pointer to the value of the heap.

Because they are careless, they are necessarily strict. Representation of laziness is impossible.

Thus, individual unboxed types, such as Int# , Double# , are actually represented as double or int on the machine (in the C notation).

Rigor analysis

Separately, the GHC does an analysis of the rigor of ordinary Haskell types. If the value is used as a string, i.e. It can never be "undefined" - the optimizer can replace all uses of the regular type (for example, Int ) with unboxed ( Int# ), because he knows that using Int always strict, and therefore replacing it with a more efficient (and always strict) type Int# safe.

Of course, we can have strict types without unpacked types, for example, a string polymorphic list:

 data List a = Empty | Cons !a (List a) 

It is strict in its elements, but does not represent them as unoccupied values.

This also indicates a mistake you made about strict languages like OCaml . They still need to maintain polymorphism, so either they provide a uniform view or they specialize data types and functions for each type. GHC uses uniform presentation by default, as does OCaml, although GHC can also now specialize types and functions (for example, C ++ templates).

+32
Jun 28 '10 at 17:27
source share

Unboxed types are necessarily strict, but not all strict values ​​are necessarily unpacked.

 data Foo a = Foo !a !a 

has two strict fields

 data Bar a = Bar {-# UNPACK #-} !Int !a 

has two string fields, but the first one is unpacked.

Ultimately, the reason the decompressed types are (necessarily) strong is that there is no place to store thunk, because they are just flat, dumb data at this point.

+17
Jun 28 '10 at 12:15
source share

Arguments of any type can be made "strict", but the only non-deferred types that have the corresponding boxed types are Char# , Int# , Word# , Double# and Float# .

If you know low-level languages ​​like C, this is easier to explain. Unboxed types are like int , double , etc., And the types in the box are like int* , double* , etc. When you have an int , you already know all the value that it represents in the bitmap, therefore it is not lazy. It must also be strict, since all int values ​​are valid and not consistent.

However, given int* , you can choose to dereference the pointer later to get the actual value (thus lazy), and it is possible to have invalid pointers (it contains & perp; i.e., non-strict).

+7
Jun 28 '10 at 16:19
source share



All Articles