Re: Discuss changing the behaviour of append()
- Posted by gimlet Jun 22, 2014
- 3351 views
Not wanting this to degenerate.
From the Haskell wikibook:
In earlier parts of the book, we have made a few passing allusions to monoids and the Monoid type class ... Here we'll give them a more detailed look and show what makes them useful. Introduction
A monoid (m, mappend, mempty) is a type m together with an associative operation mappend :: m -> m -> m (also called (<>) in Haskell) that combines two elements and a zero element mempty :: m which is the neutral element of mappend: Before describing them more formally, let's see monoids in action. Examples
As an information introduction, let's take a look at a common pattern:
> (5 + 6) + 10 == 5 + (6 + 10) True > (5 * 6) * 10 == 5 * (6 * 10) True > ("Hello" ++ " ") ++ "world!" == "Hello" ++ (" " ++ "world!") True
This property is called associativity, and it doesn't hold for only those selected values but for all integers under addition, all integers under multiplication, and all lists under concatenation.
Here's another type of pattern:
> 255 + 0 == 255 && 0 + 255 == 255 True > 255 * 1 == 255 && 1 * 255 == 255 True > [1,2,3] ++ [] == [1,2,3] && [] ++ [1,2,3] == [1,2,3] True
Here 0 is the identity element when adding integers,
1 is the identity when multiplying them, and,
[] is the identity when appending two lists.
So:
Integers form a monoid under addition where 0 is the unit: (Integer, (+), 0) Integers form a monoid under multiplication where 1 is the unit: (Integer, (*), 1) Lists form a monoid under concatenation: ([a], (++), []) ...
Take a function that concatenates three lists:
threeConcat :: [a] -> [a] -> [a] -> [a] threeConcat a b c = a b c
We can generalize this function to work with any monoid:
threeConcat' :: Monoid m => m -> m -> m -> m threeConcat' a b c = a <> b <> c
threeConcat' "Hello" " " "world!" -- "Hello world!" threeConcat' (Sum 5) (Sum 6) (Sum 10) -- Sum {getSum = 21}
Other functions like fold :: (Foldable t, Monoid m) => t m -> m from Data.Foldable use properties of monoids to reduce any foldable structure containing monoids into a single monoidal value:
fold ["Hello", " ", "world!"] -- "Hello world!" > fold (Just (Sum 10)) -- Sum {getSum = 10} > fold Nothing :: Sum Integer -- Sum {getSum = 0}
My point is not that Euphoria should be more Haskell-like but that the monoid makes it easy reasoning about functions.
Our append is strange this way. It has no identity.