[Haskell-cafe] Re: FW: Haskell

Chris Smith cdsmith at twu.net
Tue Apr 1 11:37:57 EDT 2008

Just random thoughts here.

Andrew Bagdanov wrote:
> Well, if I don't have side effects (and don't mind extra, unneeded
> evaluations), I can write my conditionals as functions in Scheme too.
> Heck, now that I think of it I can even avoid those extra evaluations
> and side-effect woes if i require promises for each branch of the
> conditional.  No macros required...

This is essentially doing lazy evaluation in Scheme.  It's certainly 
possible; just clumsy.  You must explicitly say where to force 
evaluation; but if you think about it, the run-time system already knows 
when it needs a value.  This is very analogous to having type inference 
instead of explicitly declaring a bunch of types as in Java or C++.

> Again, I think this is highly problem
> dependent, though I think you win more with lazy evaluation in the long
> run.  Do more experienced Haskellers than me have the opposite
> experience?  I mean, do you ever find yourself forcing strict evaluation
> so frequently that you just wish you could switch on strict evaluation
> as a default for a while?

The first thing I'd say is that Haskell, as a purely functional language 
that's close enough to the pure lambda calculus, has unique normal 
forms.  Furthermore, normal order (and therefore lazy) evaluation is 
guaranteed to be an effective evaluation order for reaching those normal 
forms.  Therefore, forcing strictness can never be needed to get a 
correct answer from a program.  (Applicative order evaluation does not 
have this property.)

Therefore, strictness is merely an optimization.  In some cases, it can 
improve execution time (by a constant factor) and memory usage (by a 
lot).  In other cases, it can hurt performance by doing calculations that 
are not needed.  In still more cases, it is an incorrect optimization and 
can actually break the code by causing certain expressions that should 
have an actual value to become undefined (evaluate to bottom).  I've 
certainly seen all three cases.

There are certainly situations where Haskell uses a lot of strictness 
annotations.  For example, see most of the shootout entries.  In 
practice, though, code isn't written like that.  I have rarely used any 
strictness annotations at all.  Compiling with optimization in GHC is 
usually good enough.  The occasional bang pattern (often when you intend 
to run something in the interpreter) works well enough.

(As an aside, this situation is quite consistent with the general 
worldview of the Haskell language and community.  Given that strictness 
is merely an optimization of laziness, the language itself naturally opts 
for the elegant answer, which is lazy evaluation; and then Simon and 
friends work a hundred times as hard to make up for it in GHC!)

> I think this is possibly the weakest reason to choose Haskell over
> Scheme.  Lispers like the regularity of the syntax of S-expressions, the
> fact that there is just one syntactic form to learn, understand, teach,
> and use.

I am strongly convinced, by the collective experience of a number of 
fields of human endeavor, that noisy syntax gets in the way of 
understanding.  Many people would also say that mathematical notation is 
a bit impenetrable -- capital sigmas in particular seem to scare people 
-- but I honestly think we'd be a good ways back in the advancement of 
mathematical thought if we didn't have such a brief and non-obstructive 
syntax for these things.  Mathematicians are quite irregular.  Sometimes 
they denote that y depends on x by writing y(x); sometimes by writing y_x 
(a subscript); and sometimes by writing y and suppressing x entirely in 
the notation.  These are not arbitrary choices; they are part of how 
human beings communicate with each other, by emphasizing some things, and 
suppressing others.  If one is to truly believe that computer programs 
are for human consumption, then striving for regularity in syntax doesn't 
seem consistent.

Initially, syntax appears to be on a completely different level from all 
the deep "semantic" differences; but they are in reality deeply 
interconnected.  The earlier comment I made about it being clumsy to do 
lazy programming in Scheme was precisely that the syntax is too noisy.  
Other places where lazy evaluation helps, in particular compositionality, 
could all be simulated in Scheme, but you'd have to introduce excessive 
syntax.  The result of type inference is also a quieter expression of 
code.  So if concise syntax is not desirable, then one may as well throw 
out laziness and type inference as well.  Also, sections and currying.  
Also, do notation.  And so on.

> In short, I think the orginal question must be asked in context.  For
> some problems, types are just a natural way to start thinking about
> them.  For others dynamic typing, with _judicious_ use of macros to
> model key aspects, is the most natural approach.

I wouldn't completely rule out, though, the impact of the person solving 
the problem on whether type-based problem solving is a natural and useful 
way to solve problems.  Indeed, I would guess this probably ends up being 
a greater factor, in the end, than the problem.  Unfortunately, we (as a 
general programming community) have caged ourselves into a box with the 
mantra "use the right tool for the job" such that we find it far too easy 
to dismiss something as the wrong tool merely because it is unfamiliar.  
My not being able to use a tool well may be a good reason for me, but 
it's a lousy reason for me to advise someone else.

More information about the Haskell-Cafe mailing list