摺疊結構反向

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