Donnacha Oisín Kidney
2018-05-22 21:57:29 UTC
The current semigroup instance for Maybe looks like this:
instance Semigroup a => Semigroup (Maybe a) where
Nothing <> b = b
a <> Nothing = a
Just a <> Just b = Just (a <> b)
However, it could be lazier:
instance Semigroup a => Semigroup (Maybe a) where
Nothing <> b = b
Just a <> b = Just (maybe a (a<>) b)
A different definition for `Option` gets back the old behaviour:
newtype LeftOption a = LeftOption { getLeftOption :: Maybe a }
instance Semigroup a => Semigroup (LeftOption a) where
LeftOption Nothing <> ys = ys
LeftOption (Just x) <> LeftOption ys = LeftOption (Just (maybe x (x<>) ys))
instance Semigroup a => Monoid (LeftOption a) where
mempty = LeftOption Nothing
mappend = (<>)
Is there any benefit to the extra strictness? Should this be changed?
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.
I originally posted this to reddit (https://www.reddit.com/r/haskell/comments/8lbzan/semigroup_maybe_too_strict/ <https://www.reddit.com/r/haskell/comments/8lbzan/semigroup_maybe_too_strict/>) and was encouraged to post it here.
instance Semigroup a => Semigroup (Maybe a) where
Nothing <> b = b
a <> Nothing = a
Just a <> Just b = Just (a <> b)
However, it could be lazier:
instance Semigroup a => Semigroup (Maybe a) where
Nothing <> b = b
Just a <> b = Just (maybe a (a<>) b)
Data.Monoid.getFirst . foldMap pure $ [1..]
Just 1fmap Data.Semigroup.getFirst . Data.Semigroup.getOption . foldMap (pure.pure) $ [1..]
_|_A different definition for `Option` gets back the old behaviour:
newtype LeftOption a = LeftOption { getLeftOption :: Maybe a }
instance Semigroup a => Semigroup (LeftOption a) where
LeftOption Nothing <> ys = ys
LeftOption (Just x) <> LeftOption ys = LeftOption (Just (maybe x (x<>) ys))
instance Semigroup a => Monoid (LeftOption a) where
mempty = LeftOption Nothing
mappend = (<>)
fmap Data.Semigroup.getFirst . getLeftOption . foldMap (LeftOption . Just . Data.Semigroup.First) $ [1..]
Just 1Is there any benefit to the extra strictness? Should this be changed?
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.
I originally posted this to reddit (https://www.reddit.com/r/haskell/comments/8lbzan/semigroup_maybe_too_strict/ <https://www.reddit.com/r/haskell/comments/8lbzan/semigroup_maybe_too_strict/>) and was encouraged to post it here.