Maybe
expresses computations that might not produce a result due to an error. Therefore such computations must be short circuited.
Now Maybe
's Semigroup/Monoid instances seem to break with this semantics, because the former is biased towards Just
and the latter treats the error case Nothing
as its empty element:
Just "foo" <> Nothing -- Just "foo"
Nothing <> Just "bar" -- Just "bar"
Just "foo" <> Just "bar" -- Just "foobar"
Nothing <> Nothing -- Nothing
I would expect Nothing
for the first two cases.
Here is the alternative implementation (hopefully it is correct/lawful):
instance Semigroup a => Semigroup (Maybe a) where
Nothing <> _ = Nothing
_ <> Nothing = Nothing
Just a <> Just b = Just (a <> b)
instance Monoid a => Monoid (Maybe a) where
mempty = Just mempty
I don't want to say that these alternative instances are better. But they seem useful too. So why was a selection made in the first place instead of leaving the implementation to the user?