折叠结构反向

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