1
-
函数同样接受两个参数
-
参数跟回传值是同样的类型
-
同样存在某些值当套用二元函数时并不会改变其他值 mempty `mappend` x = x
-
遵守结合律 (x `mappend` y) `mappend` z = x `mappend` (y `mappend` z)
2 import Data.Monoid
class Monoid m where
mempty :: m
mappend :: m -> m -> m
mconcat :: [m] -> m
mconcat = foldr mappend mempty
instance Monoid [a] whereLists are monoids . Product and Sum
mempty = []
mappend = (++)
newtype Product a = Product { getProduct :: a }
deriving (Eq, Ord, Read, Show, Bounded)
instance Num a => Monoid (Product a) whereAny and ALL
mempty = Product 1
Product x `mappend` Product y = Product (x * y)
newtype Any = Any { getAny :: Bool }
deriving (Eq, Ord, Read, Show, Bounded)
instance Monoid Any where
mempty = Any False
Any x `mappend` Any y = Any (x || y)
newtype All = All { getAll :: Bool }
deriving (Eq, Ord, Read, Show, Bounded)
instance Monoid All where
mempty = All True
All x `mappend` All y = All (x && y)
instance Monoid Ordering where
mempty = EQ
LT `mappend` _ = LT
EQ `mappend` y = y
GT `mappend` _ = GT
instance Monoid a => Monoid (Maybe a) where另一种有趣的 monoid 使用方式就是让他来帮助我们 fold 一些数据结构。 由于有太多种数据结构可以 fold 了,所以我们定义了
mempty = Nothing
Nothing `mappend` m = m
m `mappend` Nothing = m
Just m1 `mappend` Just m2 = Just (m1 `mappend` m2)
Foldable
这个 typeclass。就像
Functor
是定义可以 map over 的结构。
Foldable
是定义可以 fold 的结构。在
Data.Foldable
中有定义了一些有用的函数,但他们名称跟
Prelude
中的名称冲突。所以最好是用 qualified 的方式 import 他们:
import qualified Foldable as F
ghci> :t foldr
foldr :: (a -> b -> b) -> b -> [a] -> b
ghci> :t F.foldr
F.foldr :: (F.Foldable t) => (a -> b -> b) -> b -> t a -> b
foldMap :: (Monoid m, Foldable t) => (a -> m) -> t a -> m
instance F.Foldable Tree where
foldMap f Empty = mempty
foldMap f (Node x l r) = F.foldMap f l `mappend`
f x `mappend`
F.foldMap f r
3