<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>