
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