折叠结构反向
在 Dual monoid 的帮助下, 任何折叠都可以在相反的方向上运行,这会翻转现有的幺半群,以便聚合反向。
newtype Dual a = Dual { getDual::a }
instance Monoid m => Monoid (Dual m) where
    mempty = Dual mempty
    (Dual x) `mappend` (Dual y) = Dual (y `mappend` x)
当用 Dual 翻转 foldMap 调用的底层 monoid 时,折叠向后运行; 下面 Reverse 类型是在限定 Data.Functor.Reverse :
newtype Reverse t a = Reverse { getReverse::t a }
instance Foldable t => Foldable (Reverse t) where
    foldMap f = getDual . foldMap (Dual . f) . getReverse
我们可以使用这个机器为列表写一个简洁的 reverse:
reverse :: [a] -> [a]
reverse = toList . Reverse