wiki:Libraries/Proposals/SemigroupMonoid

Version 5 (modified by Herbert Valerio Riedel, 12 months ago) (diff)

try to describe ugly alternative variant

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

Recommended Variant

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.

Alternative w/ conditionally defined Semigroup instance & -XCPP

This variant can be used if you require support for GHC < 8.0 and you do not want to depend on the semigroups package.

#if MIN_VERSION_base(4,9,0)
-- Data.Semigroup was added in base-4.9
import Data.Semigroup as Sem
#endif
#if !(MIN_VERSION_base(4,8,0))
-- starting with base-4.8, Monoid is rexported from Prelude
import Data.Monoid
#endif

appendFoo :: Foo -> Foo -> Foo
appendFoo = 

emptyFoo :: Foo
emptyFoo = 

#if MIN_VERSION_base(4,9,0)
instance Sem.Semigroup Foo where
  (<>) = appendFoo
#endif

instance Monoid Foo where
  mempty = emptyFoo

#if MIN_VERSION_base(4,11,0)
-- starting with base-4.11, mappend definitions are redundant;
-- at some point `mappend` will be removed from `Monoid`
#elif MIN_VERSION_base(4,9,0)
  mappend = (Sem.<>)
#else // base < 4.9
-- prior to GHC 8.0 / base-4.9 where no `Semigroup` class existed
  mappend = appendFoo
# endif


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