ZipList Monoid haskell

前端 未结 1 825
别跟我提以往
别跟我提以往 2021-01-21 08:36

The default monoid for lists in the GHC Prelude is concatenation.

[1,2,3] <> [4,5,6] becomes [1,2,3] ++ [4,5,6] and thus [1,2,3,4,5

相关标签:
1条回答
  • 2021-01-21 09:15

    First note that ZipList’s Applicative instance already has the zippy behaviour you want.

    ghci> liftA2 (<>) (Sum <$> ZipList [1,2,3]) (Sum <$> ZipList [4,5,6]) :: ZipList Int
    ZipList [Sum 5, Sum 7, Sum 9]
    

    Then use the fact that any Applicative gives rise to a Monoid by lifting the monoidal behaviour of its contents through the monoidal functor itself. The plan is to abstract the liftA2 (<>) pattern from the expression I wrote above.

    newtype Ap f a = Ap { getAp :: f a }
    instance (Applicative f, Monoid a) => Monoid (Ap f a) where
        mempty = Ap $ pure mempty
        Ap xs `mappend` Ap ys = Ap $ liftA2 mappend xs ys
    

    (As far as I know this newtype is missing from base, which seems like an oversight to me, though there may be a good reason for it. In fact, I’d argue that ZipList should have a zippy Monoid instance out of the box, but, alas, it doesn’t.)

    Your desired Monoid is then just Ap ZipList (Sum Int). This is equivalent to the MyZipList Monoid you wrote by hand (except for the mistake in your mempty - it should be MyZipList $ ZipList $ repeat mempty), but composing it out of reusable newtypes like this is less ad-hoc and requires less boilerplate.

    0 讨论(0)
提交回复
热议问题