Laziness is not always good
From HaskellWiki
(Difference between revisions)
(first draft) |
(exercise) |
||
| Line 1: | Line 1: | ||
| - | Generally, since Haskell is a [[Non-strict_semantics|non-strict]] language, | + | Generally, since Haskell is a [[Non-strict_semantics|non-strict]] language, |
| + | you should try to make a function [[maintaining laziness|least strict]]. | ||
This is in many cases the best semantics and the most efficient implementation. | This is in many cases the best semantics and the most efficient implementation. | ||
However, here is an important exception from the rule: | However, here is an important exception from the rule: | ||
| Line 24: | Line 25: | ||
and this gets lost when the optimization is applied. | and this gets lost when the optimization is applied. | ||
| - | The solution | + | The solution of this issue is to define |
<haskell> | <haskell> | ||
mempty = () | mempty = () | ||
| Line 39: | Line 40: | ||
If you find that example too academic, you can choose any other data type with one constructor instead. | If you find that example too academic, you can choose any other data type with one constructor instead. | ||
| + | |||
| + | == Exercise == | ||
| + | |||
| + | Find out, whether it would help to define <hask>mempty = undefined</hask>. | ||
== See also == | == See also == | ||
Revision as of 20:22, 30 January 2009
Generally, since Haskell is a non-strict language, you should try to make a function least strict. This is in many cases the best semantics and the most efficient implementation. However, here is an important exception from the rule:
Consider theMonoid
()
mempty = () mappend _ _ = ()
These functions are least strict, but have a subtle problem: They do not generally satisfy the monoid laws.
Remind you:mempty
mappend
forall a. mappend mempty a = a forall a. mappend a mempty = a
mappend mempty undefined = undefined
mappend mempty undefined = mempty
Is this academic nitpicking or practically relevant?
I think it is the latter one, because aMonoid
that monoid laws can be applied in every case.
A programmer expects that every occurence ofmappend mempty a
a
You might even create an optimizer rule doing this.
The above implementation ofmappend
and this gets lost when the optimization is applied.
The solution of this issue is to define
mempty = () mappend () () = () force :: () -> () force _ = ()
and write
mappend (force a) (force b)
mappend a b
If you find that example too academic, you can choose any other data type with one constructor instead.
1 Exercise
Find out, whether it would help to definemempty = undefined
2 See also
- Haskell-Cafe on Laws and partial values
- Maintaining laziness
