You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: source_md/functors-applicative-functors-and-monoids.md
+50-31Lines changed: 50 additions & 31 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1486,18 +1486,20 @@ We call this property *associativity*.
1486
1486
`*` is associative, and so is `++`, but `-`, for example, is not.
1487
1487
The expressions `(5 - 3) - 4` and `5 - (3 - 4)` result in different numbers.
1488
1488
1489
-
By noticing and writing down these properties, we have chanced upon *monoids*!
1490
-
A monoid is when you have an associative binary function and a value which acts as an identity with respect to that function.
1489
+
By noticing and writing down these properties, we have chanced upon *semigroups* and *monoids*!
1490
+
A semigroup is when you have an associative binary function, and a monoid is when you also have a value which acts as an identity with respect to that function.
1491
1491
When something acts as an identity with respect to a function, it means that when called with that function and some other value, the result is always equal to that other value.
1492
1492
`1` is the identity with respect to `*` and `[]` is the identity with respect to `++`.
1493
-
There are a lot of other monoids to be found in the world of Haskell, which is why the `Monoid` type class exists.
1494
-
It's for types which can act like monoids.
1495
-
Let's see how the type class is defined:
1493
+
There are a lot of other monoids and semigroups to be found in the world of Haskell, which is why the `Monoid`and `Semigroup`type classes exist.
1494
+
It's for types which can act like monoids and semigroups.
1495
+
Let's see how the type classes are defined:
1496
1496
1497
1497
```{.haskell:hs}
1498
-
class Monoid m where
1499
-
mempty :: m
1498
+
class Semigroup m where
1500
1499
(<>) :: m -> m -> m
1500
+
1501
+
class Semigroup m => Monoid m where
1502
+
mempty :: m
1501
1503
mconcat :: [m] -> m
1502
1504
mconcat = foldr (<>) mempty
1503
1505
```
@@ -1508,6 +1510,8 @@ Let's take some time and get properly acquainted with it.
1508
1510
1509
1511
First of all, we see that only concrete types can be made instances of `Monoid`, because the `m` in the type class definition doesn't take any type parameters.
1510
1512
This is different from `Functor` and `Applicative`, which require their instances to be type constructors which take one parameter.
1513
+
We also see that all `Monoid`s must also be `Semigroup`s, just like all `Applicative`s must be `Functor`s.
1514
+
This is because monoids are a special kind of semigroup, as they also have an identity value.
1511
1515
1512
1516
The first function is `mempty`.
1513
1517
It's not really a function, since it doesn't take parameters, so it's a polymorphic constant, kind of like `minBound` from `Bounded`.
@@ -1527,17 +1531,18 @@ Because the default implementation is fine for most instances, we won't concern
1527
1531
When making a type an instance of `Monoid`, it suffices to just implement `mempty` and `<>`.
1528
1532
The reason `mconcat` is there at all is because for some instances, there might be a more efficient way to implement `mconcat`, but for most instances the default implementation is just fine.
1529
1533
1530
-
Before moving on to specific instances of `Monoid`, let's take a brief look at the monoid laws.
1534
+
Before moving on to specific instances of `Monoid`, let's take a brief look at the semigroup and monoid laws.
1531
1535
We mentioned that there has to be a value that acts as the identity with respect to the binary function and that the binary function has to be associative.
1532
-
It's possible to make instances of `Monoid` that don't follow these rules, but such instances are of no use to anyone because when using the `Monoid` type class, we rely on its instances acting like monoids.
1536
+
It's possible to make instances of `Semigroup` and `Monoid` that don't follow these rules, but such instances are of no use to anyone because when using the `Monoid` type class, we rely on its instances acting like monoids.
1533
1537
Otherwise, what's the point?
1534
1538
That's why when making instances, we have to make sure they follow these laws:
1535
1539
1536
-
*`mempty <> x = x`{.label .law}
1537
-
*`x <> mempty = x`{.label .law}
1538
-
*`(x <> y) <> z = x <> (y <> z)`{.label .law}
1540
+
*`(x <> y) <> z = x <> (y <> z)`{.label .law} (semigroup law)
1541
+
*`mempty <> x = x`{.label .law} (monoid law)
1542
+
*`x <> mempty = x`{.label .law} (monoid law)
1539
1543
1540
-
The first two state that `mempty` has to act as the identity with respect to `<>` and the third says that `<>` has to be associative i.e. that it the order in which we use `<>` to reduce several monoid values into one doesn't matter.
1544
+
The first says that `<>` has to be associative i.e. that the order in which we use `<>` to reduce several semigroup values into one doesn't matter, and the other two state that `mempty` has to act as the identity with respect to `<>`.
1545
+
Semigroups follow the first law, but monoids must follow all three.
1541
1546
Haskell doesn't enforce these laws, so we as the programmer have to be careful that our instances do indeed obey them.
1542
1547
1543
1548
### Lists are monoids
@@ -1547,9 +1552,11 @@ Like we've seen, the `++` function and the empty list `[]` form a monoid.
1547
1552
The instance is very simple:
1548
1553
1549
1554
```{.haskell:hs}
1555
+
instance Semigroup [a] where
1556
+
(<>) = (++)
1557
+
1550
1558
instance Monoid [a] where
1551
1559
mempty = []
1552
-
(<>) = (++)
1553
1560
```
1554
1561
1555
1562
Lists are an instance of the `Monoid` type class regardless of the type of the elements they hold.
@@ -1636,9 +1643,11 @@ Simple, just a `newtype` wrapper with one type parameter along with some derived
1636
1643
Its instance for `Monoid` goes a little something like this:
1637
1644
1638
1645
```{.haskell:hs}
1646
+
instance Num a => Semigroup (Product a) where
1647
+
Product x <> Product y = Product (x * y)
1648
+
1639
1649
instance Num a => Monoid (Product a) where
1640
1650
mempty = Product 1
1641
-
Product x <> Product y = Product (x * y)
1642
1651
```
1643
1652
1644
1653
`mempty` is just `1` wrapped in a `Product` constructor.
@@ -1690,9 +1699,11 @@ newtype Any = Any { getAny :: Bool }
1690
1699
Its instance looks goes like so:
1691
1700
1692
1701
```{.haskell:hs}
1702
+
instance Semigroup Any where
1703
+
Any x <> Any y = Any (x || y)
1704
+
1693
1705
instance Monoid Any where
1694
1706
mempty = Any False
1695
-
Any x <> Any y = Any (x || y)
1696
1707
```
1697
1708
1698
1709
The reason it's called `Any` is because `x <> y` will be `True` if *any* one of those two is `True`.
@@ -1721,9 +1732,11 @@ newtype All = All { getAll :: Bool }
1721
1732
And this is the instance:
1722
1733
1723
1734
```{.haskell:hs}
1735
+
instance Semigroup All where
1736
+
All x <> All y = All (x && y)
1737
+
1724
1738
instance Monoid All where
1725
1739
mempty = All True
1726
-
All x <> All y = All (x && y)
1727
1740
```
1728
1741
1729
1742
When we `<>` values of the `All` type, the result will be `True` only if *all* the values used in the `<>` operations are `True`:
@@ -1760,11 +1773,13 @@ With lists, numbers and boolean values, finding monoids was just a matter of loo
1760
1773
With `Ordering`, we have to look a bit harder to recognize a monoid, but it turns out that its `Monoid` instance is just as intuitive as the ones we've met so far and also quite useful:
1761
1774
1762
1775
```{.haskell:hs}
1763
-
instance Monoid Ordering where
1764
-
mempty = EQ
1776
+
instance Semigroup Ordering where
1765
1777
LT <> _ = LT
1766
1778
EQ <> y = y
1767
1779
GT <> _ = GT
1780
+
1781
+
instance Monoid Ordering where
1782
+
mempty = EQ
1768
1783
```
1769
1784
1770
1785
{.right width=330 height=339}
@@ -1859,23 +1874,25 @@ The `Ordering` monoid is very cool because it allows us to easily compare things
1859
1874
1860
1875
Let's take a look at the various ways that `Maybe a` can be made an instance of `Monoid` and what those instances are useful for.
1861
1876
1862
-
One way is to treat `Maybe a` as a monoid only if its type parameter `a` is a monoid as well and then implement `<>` in such a way that it uses the `<>` operation of the values that are wrapped with `Just`.
1877
+
One way is to treat `Maybe a` as a monoid only if its type parameter `a` is a semigroup (or even a monoid) and then implement `<>` in such a way that it uses the `<>` operation of the values that are wrapped with `Just`.
1863
1878
We use `Nothing` as the identity, and so if one of the two values that we're `<>`ing is `Nothing`, we keep the other value.
1864
1879
Here's the instance declaration:
1865
1880
1866
1881
```{.haskell:hs}
1867
-
instance Monoid a => Monoid (Maybe a) where
1868
-
mempty = Nothing
1882
+
instance Semigroup a => Semigroup (Maybe a) where
1869
1883
Nothing <> m = m
1870
1884
m <> Nothing = m
1871
1885
Just m1 <> Just m2 = Just (m1 <> m2)
1886
+
1887
+
instance Semigroup a => Monoid (Maybe a) where
1888
+
mempty = Nothing
1872
1889
```
1873
1890
1874
1891
Notice the class constraint.
1875
-
It says that `Maybe a` is an instance of `Monoid` only if `a` is an instance of `Monoid`.
1892
+
It says that `Maybe a` is an instance of `Monoid` only if `a` is an instance of `Semigroup`.
1876
1893
If we `<>` something with a `Nothing`, the result is that something.
1877
1894
If we `<>` two `Just` values, the contents of the `Just`s get `<>`ed and then wrapped back in a `Just`.
1878
-
We can do this because the class constraint ensures that the type of what's inside the `Just` is an instance of `Monoid`.
1895
+
We can do this because the class constraint ensures that the type of what's inside the `Just` is an instance of `Semigroup`.
1879
1896
1880
1897
```{.haskell:hs}
1881
1898
ghci> Nothing <> Just "andy"
@@ -1886,12 +1903,12 @@ ghci> Just (Sum 3) <> Just (Sum 4)
1886
1903
Just (Sum {getSum = 7})
1887
1904
```
1888
1905
1889
-
This comes in use when you're dealing with monoids as results of computations that may have failed.
1890
-
Because of this instance, we don't have to check if the computations have failed by seeing if they're a `Nothing` or `Just` value; we can just continue to treat them as normal monoids.
1906
+
This comes in use when you're dealing with semigroups as results of computations that may have failed.
1907
+
Because of this instance, we don't have to check if the computations have failed by seeing if they're a `Nothing` or `Just` value; we can just continue to treat them as normal semigroups.
1891
1908
1892
-
But what if the type of the contents of the `Maybe` aren't an instance of `Monoid`?
1893
-
Notice that in the previous instance declaration, the only case where we have to rely on the contents being monoids is when both parameters of `<>` are `Just` values.
1894
-
But if we don't know if the contents are monoids, we can't use `<>` between them, so what are we to do?
1909
+
But what if the type of the contents of the `Maybe` aren't an instance of `Semigroup`?
1910
+
Notice that in the previous instance declaration, the only case where we have to rely on the contents being a semigroup is when both parameters of `<>` are `Just` values.
1911
+
But if we don't know if the contents are a semigroup, we can't use `<>` between them, so what are we to do?
1895
1912
Well, one thing we can do is to just discard the second value and keep the first one.
1896
1913
For this, the `First a` type exists and this is its definition:
1897
1914
@@ -1904,10 +1921,12 @@ We take a `Maybe a` and we wrap it with a `newtype`.
0 commit comments