What's the practical value of all those newtype wrappers in `Data.Monoid`?

前端 未结 5 464
误落风尘
误落风尘 2020-12-15 21:13

When looking at Data.Monoid, I see there are various newtype wrappers, such as All, Sum, or Product, which e

5条回答
  •  一个人的身影
    2020-12-15 21:32

    How about in an instance like this:

    myData :: [(Sum Integer, Product Double)]
    myData = zip (map Sum [1..100]) (map Product [0.01,0.02..])
    
    main = print $ mconcat myData
    

    Or without the newtype wrapper and the Monoid instance:

    myData :: [(Integer, Double)]
    myData = zip [1..100] [0.01,0.02..]
    
    main = print $ foldr (\(i, d) (accI, accD) -> (i + accI, d * accD)) (0, 1) myData
    

    This is due to the fact that (Monoid a, Monoid b) => Monoid (a, b). Now, what if you had custom data types and you wanted to fold over a tuple of these values applying a binary operation? You could simply write a newtype wrapper and make it an instance of Monoid with that operation, construct your list of tuples, then just use mconcat to fold across them. There are many other functions that work on Monoids as well, not just mconcat, so there are certainly a myriad of applications.


    You could also look at the First and Last newtype wrappers for Maybe a, I can think of many uses for those. The Endo wrapper is nice if you need to compose a lot of functions, the Any and All wrappers are good for working with booleans.

提交回复
热议问题