31

There's a list of data structures having lazy and strict implementations:

  • Data.Map.Lazy and Data.Map.Strict
  • Data.IntMap.Lazy and Data.IntMap.Strict
  • Data.HashMap.Lazy and Data.HashMap.Strict
  • Data.ByteString.Lazy and Data.ByteString.Strict
  • Data.Text.Lazy and Data.Text

What are the strengths and weaknesses of those implementations and what are the rules to follow when choosing a specific one?

Nikita Volkov
  • 42,792
  • 11
  • 94
  • 169
  • 6
    I don't have any strict (heh) rules for you, but I tend to choose laziness unless I have a good reason not to. Lazy structures behave more naturally and fit better with the rest of the language. – Tikhon Jelvis Apr 30 '13 at 10:27

2 Answers2

27
  • Data.XYMap.Lazy and Data.XYMap.Strict

for XY in {"", "Int", "Hash"}: The *.Strict variant forces the evaluation of the mapped-to values to WHNF before they are placed in the map.

The big advantage of that is more predictable space and time behaviour, since it is much harder to build up huge thunks, especially for types of the form (ConstructorN UnboxedValueTypeN), that is impossible.

The disadvantage - I remember there were examples brought up when it was discussed whether the strict or lazy variants should become the default, but I don't remember anything in particular.

Ah, just remembered a use case: One can tie a knot with the Lazy variants, that is of course impossible with the Strict versions! So if you do such things: Lazy.

I use the Strict versions by default. Until I need to tie knots or encounter another use case where I consider the Lazy variants superior, I don't know when I would use them.

  • Data.(ByteString/Text).Lazy and Data.(ByteString/Text).Strict

The strict versions use one monolithic chunk of storage for the payload, that means you have fast random access, not only sequentially, but also backwards from the end, or jumping to and fro.

The lazy versions are basically head-strict lists of strict chunks, their strength is that sequential consumption of them can often be done in constant small memory, that is great if you need to sequentially process large files.

For small(ish) data, definitely use the Strict variants, for huge data the Lazy variants if the data is processed (more or less) sequentially.

Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
  • 4
    Note that the `Strict` variants are even strict in function parameters like the default value passed to `findWithDefault`, which is often *not* what you expect, even when deliberately using a strict map. – Joachim Breitner Nov 05 '13 at 08:43
23

What are the strengths and weaknesses of those implementations and what are the rules to follow when choosing a specific one?

The strictness or laziness of the type lead to different complexity of particular operations, or modes of use.

There are no hard or fast rules - instead, you might like to think of them as entirely different data types.

If you insist on some guidelines:

  • lazy structures for data larger than memory
  • lazy structures for infrequently used data or when you use a small part of a large structure

And then:

  • strict structures if you do lots of updates
  • strict structures for small, atomic data
Don Stewart
  • 137,316
  • 36
  • 365
  • 468