on master help sign in
Replace the Monoid instance on Maybe

The current default Monoid instance for Maybe is like that in Haskell, where a semigroup operator on the underlying type is used to collect successes. Conor argues convincingly that this is not the right notion of computation for Maybe [1], so I figured I'd fix it while we're young. [1] https://www.reddit.com/r/haskell/comments/30s1t2/proposal_make_semigroup_as_a_superclass_of_monoid/cpvdco1 The old behavior is available in a named instance, and both are documented.

commit220011e4c8f46d0eb2fc64add0eeefc8c210aa95 authorDavid Raymond Christiansen <david@davidchristiansen.dk> dateThu 2 Apr 2015, 08:06 (12 years ago) parent663c401
2 files changed+21−10
CHANGELOG+3 libs/prelude/Prelude/Maybe.idr+18−10
CHANGELOG+3
@@ -21,6 +21,9 @@ New in 0.9.18:
2121 requiring a separate lemma.
2222* Case alternatives are allowed to be impossible:
2323 case Vect.Nil {a=Nat} of { (x::xs) impossible ; [] => True }
24+* The default Semigroup and Monoid instances for Maybe are now prioritised
25+ choice, keeping the first success as Alternative does. The version that
26+ collects successes is now a named instance.
2427
2528New in 0.9.17:
2629--------------
libs/prelude/Prelude/Maybe.idr+18−10
@@ -78,17 +78,25 @@ instance (Eq a) => Eq (Maybe a) where
7878 (Just _) == Nothing = False
7979 (Just a) == (Just b) = a == b
8080
81−-- Lift a semigroup into 'Maybe' forming a 'Monoid' according to
82−-- <http://en.wikipedia.org/wiki/Monoid>: "Any semigroup S may be
83−-- turned into a monoid simply by adjoining an element i not in S
84−-- and defining i+i = i and i+s = s = s+i for all s in S."
85−
86−instance (Semigroup a) => Semigroup (Maybe a) where
87− Nothing <+> m = m
88− m <+> Nothing = m
81+||| Prioritised choice. Just like the `Alternative` instance, the
82+||| `Semigroup` for `Maybe a` keeps the first succeeding computation.
83+|||
84+||| **NB**: This is a different choice than in the Haskell libraries.
85+||| Use `collectJust` to get the Haskell behaviour.
86+instance Semigroup (Maybe a) where
87+ Nothing <+> m = m
88+ (Just x) <+> _ = Just x
89+
90+||| Transform any semigroup into a monoid by using `Nothing` as the
91+||| designated neutral element and collecting the contents of the
92+||| `Just` constructors using a semigroup structure on `a`. This is
93+||| the behaviour in the Haskell libraries.
94+instance [collectJust] Semigroup a => Semigroup (Maybe a) where
95+ Nothing <+> m = m
96+ m <+> Nothing = m
8997 (Just m1) <+> (Just m2) = Just (m1 <+> m2)
9098
91−instance (Semigroup a) => Monoid (Maybe a) where
99+instance Monoid (Maybe a) where
92100 neutral = Nothing
93101
94102instance (Monoid a, Eq a) => Cast a (Maybe a) where
@@ -98,5 +106,5 @@ instance (Monoid a) => Cast (Maybe a) a where
98106 cast = lowerMaybe
99107
100108instance Foldable Maybe where
101− foldr _ z Nothing = z
109+ foldr _ z Nothing = z
102110 foldr f z (Just x) = f x z