wiki:Libraries/Proposals/SemigroupMonoid

Version 4 (modified by Herbert Valerio Riedel, 13 months ago) (diff)

fix links to GHC trac

Semigroup (as superclass of) Monoid Proposal

THIS DESCRIPTION IS STILL WORK IN PROGRESS

Please comment on ghc:#10365 or ghc:#14191 if you notice some show-stopper issue

Introducing Semigroup as a superclass of Monoid has been proposed several times (in reverse chronological order):

Final API

The final API (suitable for Haskell Report inclusion) we want to end up with is

module Data.Semigroup where

class Semigroup a where
    (<>) :: a -> a -> a

    sconcat :: NonEmpty a -> a
    sconcat (a :| as) = go a as
      where
        go b (c:cs) = b <> go c cs
        go b []     = b

    -- GHC extension, not needed for Haskell Report
    stimes :: Integral b => b -> a -> a
    stimes y0 x0 = {- default impl -}
module Data.Monoid where

class Semigroup a => Monoid a where
    mempty  :: a

    mconcat :: [a] -> a
    mconcat = foldr (<>) mempty

    -- GHC extension, not needed for Haskell Report
    mtimes :: Integral b => b -> a -> a
    mtimes y0 x0 = {- default impl -}

-- GHC Extension: Legacy alias not needed for Haskell Report
mappend :: Semigroup a => a -> a -> a
mappend = (<>)

Migration plan

Phase 1 (GHC 8.0) ghc:#10365

  • Move Data.Semigroup & Data.List.NonEmpty from semigroups-0.18 to base.
  • (maybe) Implement a warning about definitions of an operator named (<>) that indicate it will be coming into Prelude in 8.2. We should warn about missing Semigroup instances at any use site of (<>) as they'll break in phase 2.

Phase 2a (GHC 8.4) ghc:#14191

  • move Semigroup class into prelude in anticipation of it becoming a superclass of Monoid

Phase 2b (GHC 8.4) ghc:#14191

  • Make Semigroup a superclass of Monoid

Phase 3

  • Deprecate manual definitions of mappend (c.f. "Monad of no return Proposal")
  • encourage overriding the current default-implementation of (<>) via MINIMAL pragma

Phase 4

  • Move the now deprecated mappend method out of the Monoid class, and possibly turn mappend into a legacy top-level binding (c.f. "Monad of no return Proposal")

Writing compatible code

The code below is expected to be -Wcompat -Wall clean (see also https://groups.google.com/forum/#!msg/haskell-core-libraries/PyxpE2ebS9Q/Ni0ywo_GCgAJ)

import Data.Semigroup as Sem
-- base >= 4.8: `Monoid` class is exported via `Prelude`
-- base < 4.11: re-exports `Monoid` class & common newtype wrappers
-- base >= 4.11: doesn't reexport `Monoid` class anymore

instance Sem.Semigroup Foo where
  (<>) = 

instance Monoid Foo where
  mempty = 

#if !(MIN_VERSION_base(4,11,0))
  -- this is redundant starting with base-4.11 / GHC 8.4
  -- if you want to avoid CPP, you can define `mappend = (<>)` unconditionally
  mappend = (<>)
#endif

If you need compatiblity with GHC prior to version 8.0 you can avoid -XCPP by depending conditionally on semigroups via

if !impl(ghc >= 8.0)
  build-depends: semigroups == 0.18.*

to provide a legacy Semigroup class.


TODO …integrate migration roadmap outlined in http://permalink.gmane.org/gmane.comp.lang.haskell.libraries/24526