<html><head><meta http-equiv="Content-Type" content="text/html; charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">The current semigroup instance for Maybe looks like this:<br class=""><br class=""><font face="Menlo" class=""> instance Semigroup a => Semigroup (Maybe a) where<br class=""> Nothing <> b = b<br class=""> a <> Nothing = a<br class=""> Just a <> Just b = Just (a <> b)</font><br class=""><br class="">However, it could be lazier:<br class=""><br class=""><font face="Menlo" class=""> instance Semigroup a => Semigroup (Maybe a) where<br class=""> Nothing <> b = b<br class=""> Just a <> b = Just (maybe a (a<>) b)<br class=""></font><br class="">This causes different behaviour for <a href="http://hackage.haskell.org/package/base-4.11.1.0/docs/Data-Semigroup.html#t:First" class="">Data.Semigroup.First</a> and <a href="http://hackage.haskell.org/package/base-4.11.1.0/docs/Data-Monoid.html#t:First" class="">Data.Monoid.First</a>:<br class=""><br class=""><font face="Menlo" class=""> >>> Data.Monoid.getFirst . foldMap pure $ [1..]<br class=""> Just 1<br class=""> >>> fmap Data.Semigroup.getFirst . Data.Semigroup.getOption . foldMap (pure.pure) $ [1..]<br class=""> _|_</font><br class=""><br class="">A different definition for `Option` gets back the old behaviour:<br class=""><br class=""><font face="Menlo" class=""> newtype LeftOption a = LeftOption { getLeftOption :: Maybe a }<br class=""> <br class=""> instance Semigroup a => Semigroup (LeftOption a) where<br class=""> LeftOption Nothing <> ys = ys<br class=""> LeftOption (Just x) <> LeftOption ys = LeftOption (Just (maybe x (x<>) ys))<br class=""> <br class=""> instance Semigroup a => Monoid (LeftOption a) where<br class=""> mempty = LeftOption Nothing<br class=""> mappend = (<>)<br class=""> <br class=""> >>> fmap Data.Semigroup.getFirst . getLeftOption . foldMap (LeftOption . Just . Data.Semigroup.First) $ [1..]<br class=""> Just 1</font><br class=""><br class="">Is there any benefit to the extra strictness? Should this be changed?<div class=""><br class=""></div><div class="">Another consideration is that the definition could equivalently be right-strict, to get the desired behaviour for Last, but I think the left-strict definition probably follows the conventions more.</div><div class=""><br class=""></div><div class="">I originally posted this to reddit (<a href="https://www.reddit.com/r/haskell/comments/8lbzan/semigroup_maybe_too_strict/" class="">https://www.reddit.com/r/haskell/comments/8lbzan/semigroup_maybe_too_strict/</a>) and was encouraged to post it here.</div></body></html>