[Haskell-cafe] Haskell's "historical futurism" needs better writing, not better tools
Ben Franksen
ben.franksen at online.de
Fri Oct 1 01:42:39 UTC 2021
Am 17.09.21 um 07:15 schrieb Michael Turner:
> I might have missed your link to "Monoid" because my attention fell on
> "monoid mappend". Sorry for that.
>
> "The contribution of each element to the final result is combined with an
> accumulator via an /operator/ function. The operator may be explicitly
> provided by the caller as in `foldr` or may be implicit as in `length`. In
> the case of `foldMap`, the caller provides a function mapping each element
> into a suitable 'Monoid', which makes it possible to merge the per-element
> contributions via that monoid's `mappend` function."
>
> This is a little better, but I'd write it this way, I think.
>
> "Folds take operators as arguments. In some cases, it's implicit, as
> in the function "length". These operators are applied to elements when
> lazy evaluation requires it, with a fold 'accumulator' as one of the
> operands. 'foldMap' uses a function (implicit? explicit?) that maps
> elements into . . . ."
The problem you two are both facing is this: you want to describe,
abstractly, generally, the common principle behind an ad-hoc
lumped-together set of functions. This is very likely to result in
contortions and provides you with no insight.
You need to realize that these methods are all simple specializations of
two or three basic functions. The only reason they are methods of the
class is to allow specialized implementations for optimization.
Foldable is a very bad example to learn from. IMO its documentation
should only describe 'toList', define foldMap and fold in terms of foldr
or foldl, and otherwise refer you to the functions in Data.List. These
are documented in simple terms.
The best description for foldr I have ever come across is this: "foldr f
z l replaces in the list l the data constructors [] and (:) with z and
f, respectively." Once you understand the list data type and remember
that (:) is right associative, this makes foldr totally obvious. Left
folds are a bit less immediately intuitive as they go against the
"natural" associativity, but you can think of foldl as being the
analogue of foldr for "snoc" lists (lists with cheap addition of
elements at the right end), but implemented for normal lists.
Once you understand that, everything else are trivial specializations,
such as
sum = foldl' (+) 0
The only real subtlety is foldl vs. foldl' i.e. lazy vs. strict. This is
quite difficult to understand, as it requires to go pretty deep into the
evaluation model of Haskell, but for a beginner it suffices to know that
you probably want to use foldl'.
Once you understand how folds and their various specialisations work for
lists, generalizing that knowledge to Foldable structures is trivial:
just think
Data.Foldable.foldr f z l = Data.List.foldr f z (toList l)
etc.
Cheers
Ben
--
I would rather have questions that cannot be answered, than answers that
cannot be questioned. -- Richard Feynman
More information about the Haskell-Cafe
mailing list