On 10/12/09 12:07, Magnus Therning wrote:

As I understand it it all started with laziness.  I don't know if
laziness is impossible without purity, but talks and papers tend to
say something like "laziness has kept Haskell pure".
This is true, but laziness has its own advantages. Suppose I have two modules, Foo and Bar. Foo generates a data structure which is then consumed by Bar (possibly with some other component calling both of them). In a strict language I have to choose between one of these three options:

  1. Foo generates the structure all at once, and some kind of
     reference is then passed to Bar.  This is nice, simple and
     modular, but it only works for small structures.  There can also
     be a problem if the structure is slow to generate but is only
     consumed a bit at a time (e.g. by the user interface) because Bar
     can only start work once Foo has finished the whole thing.  You
     may also find the Foo is doing lots of unnecessary work building
     bits of the structure that Bar uses only rarely.
  2. Foo and Bar are built together in a single module with their
     functionality interleaved.  This means that Foo can build a bit of
     the structure, have Bar process it, and so on.  However it also
     destroys any modularity the system might have had.  If Bar is part
     of the user interface, for instance, it means that core
     functionality gets mixed up.
  3. Implement some kind of generator object.  This takes a lot of code
     and makes the logic of Foo and Bar harder to follow.  For instance
     the version of Foo from option 1 might have had a loop of the form
     "foreach i in xs".  Now "i" has to be turned into some kind of
     member variable with logic to move to the next instance.  Of
     course what you are really doing is creating an ad-hoc hand-coded
     version of lazy evaluation.

Different applications are going to require different choices. Worse yet, the right answer can change. For instance you may start with option 1, then discover that the program runs too slowly. Or marketing decide that the maximum size of the data structure has to be increased. So at that point you have to rewrite a big chunk of code. Or else you go with option 2 or 3 because the designer thought it was necessary for efficiency when in fact option 1 would have done nicely.

Of course with lazy evaluation you get option 3 all the time automatically. So its just not a problem. This makes the design much simpler because things that previously had to be decided by a human are now decided by the compiler.

Paul.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to