shithub: MicroHs

Download patch

ref: a855d4546080dfe88c5d24cce7a3b9b2e741fcda
parent: e3102605c0ddbfc934662455f4c849a49ecb2a33
author: Lennart Augustsson <lennart@augustsson.net>
date: Sun Sep 22 21:07:41 EDT 2024

Add missing files.

--- /dev/null
+++ b/lib/Data/Foldable1.hs
@@ -1,0 +1,571 @@
+-- |
+-- Copyright: Edward Kmett, Oleg Grenrus
+-- License: BSD-3-Clause
+--
+-- A class of non-empty data structures that can be folded to a summary value.
+--
+-- @since 4.18.0.0
+
+{-# LANGUAGE FlexibleInstances          #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE NoImplicitPrelude          #-}
+{-# LANGUAGE PolyKinds                  #-}
+{-# LANGUAGE ScopedTypeVariables        #-}
+{-# LANGUAGE StandaloneDeriving         #-}
+{-# LANGUAGE Trustworthy                #-}
+{-# LANGUAGE TypeOperators              #-}
+
+module Data.Foldable1 (
+    Foldable1(..),
+    foldr1, foldr1',
+    foldl1, foldl1',
+    intercalate1,
+    foldrM1,
+    foldlM1,
+    foldrMapM1,
+    foldlMapM1,
+    maximumBy,
+    minimumBy,
+    ) where
+import Data.Foldable      (Foldable, foldlM, foldr)
+import Data.List          ([](..), foldl, foldl')
+import Data.List.NonEmpty (NonEmpty (..))
+import Data.Maybe
+import Data.Semigroup
+import Data.Tuple (Solo (..))
+import Prelude
+       (Maybe (..), Monad (..), Ord, Ordering (..), id, seq, ($!), ($), (.),
+       (=<<), flip, const, error)
+
+import qualified Data.List.NonEmpty as NE
+
+import Data.Complex (Complex (..))
+
+import Data.Ord (Down (..))
+
+import qualified Data.Monoid as Mon
+
+-- Instances
+import Data.Functor.Compose          (Compose (..))
+import Data.Functor.Identity         (Identity (..))
+
+import qualified Data.Functor.Product as Functor
+import qualified Data.Functor.Sum     as Functor
+
+-- coerce
+--import GHC.Internal.Data.Coerce (Coercible, coerce)
+
+-- $setup
+-- >>> import Prelude hiding (foldr1, foldl1, head, last, minimum, maximum)
+
+-------------------------------------------------------------------------------
+-- Foldable1 type class
+-------------------------------------------------------------------------------
+
+-- | Non-empty data structures that can be folded.
+--
+-- @since 4.18.0.0
+class Foldable t => Foldable1 t where
+    {-# MINIMAL foldMap1 | foldrMap1 #-}
+
+    -- At some point during design it was possible to define this class using
+    -- only 'toNonEmpty'. But it seems a bad idea in general.
+    --
+    -- So currently we require either foldMap1 or foldrMap1
+    --
+    -- * foldMap1 defined using foldrMap1
+    -- * foldrMap1 defined using foldMap1
+    --
+    -- One can always define an instance using the following pattern:
+    --
+    --     toNonEmpty = ...
+    --     foldMap f     = foldMap f     . toNonEmpty
+    --     foldrMap1 f g = foldrMap1 f g . toNonEmpty
+
+    -- | Given a structure with elements whose type is a 'Semigroup', combine
+    -- them via the semigroup's @('<>')@ operator. This fold is
+    -- right-associative and lazy in the accumulator. When you need a strict
+    -- left-associative fold, use 'foldMap1'' instead, with 'id' as the map.
+    --
+    -- @since 4.18.0.0
+    fold1 :: Semigroup m => t m -> m
+    fold1 = foldMap1 id
+
+    -- | Map each element of the structure to a semigroup, and combine the
+    -- results with @('<>')@. This fold is right-associative and lazy in the
+    -- accumulator. For strict left-associative folds consider 'foldMap1''
+    -- instead.
+    --
+    -- >>> foldMap1 (:[]) (1 :| [2, 3, 4])
+    -- [1,2,3,4]
+    --
+    -- @since 4.18.0.0
+    foldMap1 :: Semigroup m => (a -> m) -> t a -> m
+    foldMap1 f = foldrMap1 f (\a m -> f a <> m)
+
+    -- | A left-associative variant of 'foldMap1' that is strict in the
+    -- accumulator. Use this for strict reduction when partial results are
+    -- merged via @('<>')@.
+    --
+    -- >>> foldMap1' Sum (1 :| [2, 3, 4])
+    -- Sum {getSum = 10}
+    --
+    -- @since 4.18.0.0
+    foldMap1' :: Semigroup m => (a -> m) -> t a -> m
+    foldMap1' f = foldlMap1' f (\m a -> m <> f a)
+
+    -- | 'NonEmpty' list of elements of a structure, from left to right.
+    --
+    -- >>> toNonEmpty (Identity 2)
+    -- 2 :| []
+    --
+    -- @since 4.18.0.0
+    toNonEmpty :: t a -> NonEmpty a
+    toNonEmpty = runNonEmptyDList . foldMap1 singleton
+
+    -- | The largest element of a non-empty structure.
+    --
+    -- >>> maximum (32 :| [64, 8, 128, 16])
+    -- 128
+    --
+    -- @since 4.18.0.0
+    maximum :: Ord a => t a -> a
+    maximum = getMax . foldMap1' Max
+
+    -- | The least element of a non-empty structure.
+    --
+    -- >>> minimum (32 :| [64, 8, 128, 16])
+    -- 8
+    --
+    -- @since 4.18.0.0
+    minimum :: Ord a => t a -> a
+    minimum = getMin . foldMap1' Min
+
+    -- | The first element of a non-empty structure.
+    --
+    -- >>> head (1 :| [2, 3, 4])
+    -- 1
+    --
+    -- @since 4.18.0.0
+    head :: t a -> a
+    head = getFirst . foldMap1 First
+
+    -- | The last element of a non-empty structure.
+    --
+    -- >>> last (1 :| [2, 3, 4])
+    -- 4
+    --
+    -- @since 4.18.0.0
+    last :: t a -> a
+    last = getLast . foldMap1 Last
+
+    -- | Right-associative fold of a structure, lazy in the accumulator.
+    --
+    -- In case of 'NonEmpty' lists, 'foldrMap1', when given a function @f@, a
+    -- binary operator @g@, and a list, reduces the list using @g@ from right to
+    -- left applying @f@ to the rightmost element:
+    --
+    -- > foldrMap1 f g (x1 :| [x2, ..., xn1, xn]) == x1 `g` (x2 `g` ... (xn1 `g` (f xn))...)
+    --
+    -- Note that since the head of the resulting expression is produced by
+    -- an application of @g@ to the first element of the list, if @g@ is lazy
+    -- in its right argument, 'foldrMap1' can produce a terminating expression
+    -- from an unbounded list.
+    --
+    -- For a general 'Foldable1' structure this should be semantically identical
+    -- to:
+    --
+    -- @foldrMap1 f g = foldrMap1 f g . 'toNonEmpty'@
+    --
+    -- @since 4.18.0.0
+    foldrMap1 :: (a -> b) -> (a -> b -> b) -> t a -> b
+    foldrMap1 f g xs =
+        appFromMaybe (foldMap1 (FromMaybe . h) xs) Nothing
+      where
+        h a Nothing  = f a
+        h a (Just b) = g a b
+
+    -- | Left-associative fold of a structure but with strict application of the
+    -- operator.
+    --
+    -- This ensures that each step of the fold is forced to Weak Head Normal
+    -- Form before being applied, avoiding the collection of thunks that would
+    -- otherwise occur. This is often what you want to strictly reduce a
+    -- finite structure to a single strict result.
+    --
+    -- For a general 'Foldable1' structure this should be semantically identical
+    -- to:
+    --
+    -- @foldlMap1' f z = foldlMap1' f z . 'toNonEmpty'@
+    --
+    -- @since 4.18.0.0
+    foldlMap1' :: (a -> b) -> (b -> a -> b) -> t a -> b
+    foldlMap1' f g xs =
+        foldrMap1 f' g' xs SNothing
+      where
+        -- f' :: a -> SMaybe b -> b
+        f' a SNothing  = f a
+        f' a (SJust b) = g b a
+
+        -- g' :: a -> (SMaybe b -> b) -> SMaybe b -> b
+        g' a x SNothing  = x $! SJust (f a)
+        g' a x (SJust b) = x $! SJust (g b a)
+
+    -- | Left-associative fold of a structure, lazy in the accumulator.  This is
+    -- rarely what you want, but can work well for structures with efficient
+    -- right-to-left sequencing and an operator that is lazy in its left
+    -- argument.
+    --
+    -- In case of 'NonEmpty' lists, 'foldlMap1', when given a function @f@, a
+    -- binary operator @g@, and a list, reduces the list using @g@ from left to
+    -- right applying @f@ to the leftmost element:
+    --
+    -- > foldlMap1 f g (x1 :| [x2, ..., xn]) == (...(((f x1) `g` x2) `g`...) `g` xn
+    --
+    -- Note that to produce the outermost application of the operator the entire
+    -- input list must be traversed. This means that 'foldlMap1' will diverge if
+    -- given an infinite list.
+    --
+    -- If you want an efficient strict left-fold, you probably want to use
+    -- 'foldlMap1''  instead of 'foldlMap1'. The reason for this is that the
+    -- latter does not force the /inner/ results (e.g. @(f x1) \`g\` x2@ in the
+    -- above example) before applying them to the operator (e.g. to
+    -- @(\`g\` x3)@). This results in a thunk chain \(O(n)\) elements long,
+    -- which then must be evaluated from the outside-in.
+    --
+    -- For a general 'Foldable1' structure this should be semantically identical
+    -- to:
+    --
+    -- @foldlMap1 f g = foldlMap1 f g . 'toNonEmpty'@
+    --
+    -- @since 4.18.0.0
+    foldlMap1 :: (a -> b) -> (b -> a -> b) -> t a -> b
+    foldlMap1 f g xs =
+        appFromMaybe (getDual (foldMap1 ((Dual . FromMaybe) . h) xs)) Nothing
+      where
+        h a Nothing  = f a
+        h a (Just b) = g b a
+
+    -- | 'foldrMap1'' is a variant of 'foldrMap1' that performs strict reduction
+    -- from right to left, i.e. starting with the right-most element. The input
+    -- structure /must/ be finite, otherwise 'foldrMap1'' runs out of space
+    -- (/diverges/).
+    --
+    -- If you want a strict right fold in constant space, you need a structure
+    -- that supports faster than \(O(n)\) access to the right-most element.
+    --
+    -- This method does not run in constant space for structures such as
+    -- 'NonEmpty' lists that don't support efficient right-to-left iteration and
+    -- so require \(O(n)\) space to perform right-to-left reduction. Use of this
+    -- method with such a structure is a hint that the chosen structure may be a
+    -- poor fit for the task at hand. If the order in which the elements are
+    -- combined is not important, use 'foldlMap1'' instead.
+    --
+    -- @since 4.18.0.0
+    foldrMap1' :: (a -> b) -> (a -> b -> b) -> t a -> b
+    foldrMap1' f g xs =
+        foldlMap1 f' g' xs SNothing
+      where
+        f' a SNothing  = f a
+        f' a (SJust b) = g a b
+
+        g' bb a SNothing  = bb $! SJust (f a)
+        g' bb a (SJust b) = bb $! SJust (g a b)
+
+-------------------------------------------------------------------------------
+-- Combinators
+-------------------------------------------------------------------------------
+
+-- | A variant of 'foldrMap1' where the rightmost element maps to itself.
+--
+-- @since 4.18.0.0
+foldr1 :: Foldable1 t => (a -> a -> a) -> t a -> a
+foldr1 = foldrMap1 id
+{-# INLINE foldr1 #-}
+
+-- | A variant of 'foldrMap1'' where the rightmost element maps to itself.
+--
+-- @since 4.18.0.0
+foldr1' :: Foldable1 t => (a -> a -> a) -> t a -> a
+foldr1' = foldrMap1' id
+{-# INLINE foldr1' #-}
+
+-- | A variant of 'foldlMap1' where the leftmost element maps to itself.
+--
+-- @since 4.18.0.0
+foldl1 :: Foldable1 t => (a -> a -> a) -> t a -> a
+foldl1 = foldlMap1 id
+{-# INLINE foldl1 #-}
+
+-- | A variant of 'foldlMap1'' where the leftmost element maps to itself.
+--
+-- @since 4.18.0.0
+foldl1' :: Foldable1 t => (a -> a -> a) -> t a -> a
+foldl1' = foldlMap1' id
+{-# INLINE foldl1' #-}
+
+-- | Insert an @m@ between each pair of @t m@.
+--
+-- >>> intercalate1 ", " $ "hello" :| ["how", "are", "you"]
+-- "hello, how, are, you"
+--
+-- >>> intercalate1 ", " $ "hello" :| []
+-- "hello"
+--
+-- >>> intercalate1 mempty $ "I" :| ["Am", "Fine", "You?"]
+-- "IAmFineYou?"
+--
+-- @since 4.18.0.0
+intercalate1 :: (Foldable1 t, Semigroup m) => m -> t m -> m
+intercalate1 = flip intercalateMap1 id
+
+intercalateMap1 :: (Foldable1 t, Semigroup m) => m -> (a -> m) -> t a -> m
+intercalateMap1 j f = flip joinee j . foldMap1 (JoinWith . const . f)
+
+-- | Monadic fold over the elements of a non-empty structure,
+-- associating to the right, i.e. from right to left.
+--
+-- @since 4.18.0.0
+foldrM1 :: (Foldable1 t, Monad m) => (a -> a -> m a) -> t a -> m a
+foldrM1 = foldrMapM1 return
+
+-- | Map variant of 'foldrM1'.
+--
+-- @since 4.18.0.0
+foldrMapM1 :: (Foldable1 t, Monad m) => (a -> m b) -> (a -> b -> m b) -> t a -> m b
+foldrMapM1 g f = go . toNonEmpty
+  where
+    go (e:|es) =
+      case es of
+        []   -> g e
+        x:xs -> f e =<< go (x:|xs)
+
+-- | Monadic fold over the elements of a non-empty structure,
+-- associating to the left, i.e. from left to right.
+--
+-- @since 4.18.0.0
+foldlM1 :: (Foldable1 t, Monad m) => (a -> a -> m a) -> t a -> m a
+foldlM1 = foldlMapM1 return
+
+-- | Map variant of 'foldlM1'.
+--
+-- @since 4.18.0.0
+foldlMapM1 :: (Foldable1 t, Monad m) => (a -> m b) -> (b -> a -> m b) -> t a -> m b
+foldlMapM1 g f t = g x >>= \y -> foldlM f y xs
+  where x:|xs = toNonEmpty t
+
+-- | The largest element of a non-empty structure with respect to the
+-- given comparison function.
+--
+-- @since 4.18.0.0
+maximumBy :: Foldable1 t => (a -> a -> Ordering) -> t a -> a
+maximumBy cmp = foldl1' max'
+  where max' x y = case cmp x y of
+                        GT -> x
+                        _  -> y
+
+-- | The least element of a non-empty structure with respect to the
+-- given comparison function.
+--
+-- @since 4.18.0.0
+minimumBy :: Foldable1 t => (a -> a -> Ordering) -> t a -> a
+minimumBy cmp = foldl1' min'
+  where min' x y = case cmp x y of
+                        GT -> y
+                        _  -> x
+
+-------------------------------------------------------------------------------
+-- Auxiliary types
+-------------------------------------------------------------------------------
+
+-- | Used for default toNonEmpty implementation.
+newtype NonEmptyDList a = NEDL { unNEDL :: [a] -> NonEmpty a }
+
+instance Semigroup (NonEmptyDList a) where
+  xs <> ys = NEDL (unNEDL xs . NE.toList . unNEDL ys)
+  {-# INLINE (<>) #-}
+
+-- | Create dlist with a single element
+singleton :: a -> NonEmptyDList a
+singleton = NEDL . (:|)
+
+-- | Convert a dlist to a non-empty list
+runNonEmptyDList :: NonEmptyDList a -> NonEmpty a
+runNonEmptyDList = ($ []) . unNEDL
+{-# INLINE runNonEmptyDList #-}
+
+-- | Used for foldrMap1 and foldlMap1 definitions
+newtype FromMaybe b = FromMaybe { appFromMaybe :: Maybe b -> b }
+
+instance Semigroup (FromMaybe b) where
+    FromMaybe f <> FromMaybe g = FromMaybe (f . Just . g)
+
+-- | Strict maybe, used to implement default foldlMap1' etc.
+data SMaybe a = SNothing | SJust !a
+
+-- | Used to implement intercalate1/Map
+newtype JoinWith a = JoinWith {joinee :: (a -> a)}
+
+instance Semigroup a => Semigroup (JoinWith a) where
+  JoinWith a <> JoinWith b = JoinWith $ \j -> a j <> j <> b j
+
+-------------------------------------------------------------------------------
+-- Instances for misc base types
+-------------------------------------------------------------------------------
+
+-- | @since 4.18.0.0
+instance Foldable1 NonEmpty where
+    foldMap1 f (x :| xs) = go (f x) xs where
+        go y [] = y
+        go y (z : zs) = y <> go (f z) zs
+
+    foldMap1' f (x :| xs) = foldl' (\m y -> m <> f y) (f x) xs
+
+    toNonEmpty = id
+
+    foldrMap1 g f (x :| xs) = go x xs where
+        go y [] = g y
+        go y (z : zs) = f y (go z zs)
+
+    foldlMap1  g f (x :| xs) = foldl f (g x) xs
+    foldlMap1' g f (x :| xs) = let gx = g x in gx `seq` foldl' f gx xs
+
+    head = NE.head
+    last = NE.last
+
+{-
+-- | @since 4.18.0.0
+instance Foldable1 Down where
+    foldMap1 = coerce
+
+-- | @since 4.18.0.0
+instance Foldable1 Complex where
+    foldMap1 f (x :+ y) = f x <> f y
+
+    toNonEmpty (x :+ y) = x :| y : []
+
+-------------------------------------------------------------------------------
+-- Instances for tuples
+-------------------------------------------------------------------------------
+
+-- 3+ tuples are not Foldable/Traversable
+
+-- | @since 4.18.0.0
+instance Foldable1 Solo where
+    foldMap1 f (MkSolo y) = f y
+    toNonEmpty (MkSolo x) = x :| []
+    minimum (MkSolo x) = x
+    maximum (MkSolo x) = x
+    head (MkSolo x) = x
+    last (MkSolo x) = x
+
+-- | @since 4.18.0.0
+instance Foldable1 ((,) a) where
+    foldMap1 f (_, y) = f y
+    toNonEmpty (_, x) = x :| []
+    minimum (_, x) = x
+    maximum (_, x) = x
+    head (_, x) = x
+    last (_, x) = x
+-}
+
+-------------------------------------------------------------------------------
+-- Monoid / Semigroup instances
+-------------------------------------------------------------------------------
+
+{-
+-- | @since 4.18.0.0
+instance Foldable1 Dual where
+    foldMap1 = coerce
+
+-- | @since 4.18.0.0
+instance Foldable1 Sum where
+    foldMap1 = coerce
+
+-- | @since 4.18.0.0
+instance Foldable1 Product where
+    foldMap1 = coerce
+
+-- | @since 4.18.0.0
+instance Foldable1 Min where
+    foldMap1 = coerce
+
+-- | @since 4.18.0.0
+instance Foldable1 Max where
+    foldMap1 = coerce
+
+-- | @since 4.18.0.0
+instance Foldable1 First where
+    foldMap1 = coerce
+
+-- | @since 4.18.0.0
+instance Foldable1 Last where
+    foldMap1 = coerce
+
+-- | @since 4.18.0.0
+deriving instance (Foldable1 f) => Foldable1 (Mon.Alt f)
+
+-- | @since 4.18.0.0
+deriving instance (Foldable1 f) => Foldable1 (Mon.Ap f)
+-}
+
+-------------------------------------------------------------------------------
+-- Extra instances
+-------------------------------------------------------------------------------
+
+{-
+-- | @since 4.18.0.0
+instance Foldable1 Identity where
+    foldMap1      = coerce
+
+    foldrMap1  g _ = coerce g
+    foldrMap1' g _ = coerce g
+    foldlMap1  g _ = coerce g
+    foldlMap1' g _ = coerce g
+
+    toNonEmpty (Identity x) = x :| []
+
+    last    = coerce
+    head    = coerce
+    minimum = coerce
+    maximum = coerce
+-}
+
+-- | It would be enough for either half of a product to be 'Foldable1'.
+-- Other could be 'Foldable'.
+instance (Foldable1 f, Foldable1 g) => Foldable1 (Functor.Product f g) where
+    foldMap1 f (Functor.Pair x y)    = foldMap1 f x <> foldMap1 f y
+    foldrMap1 g f (Functor.Pair x y) = foldr f (foldrMap1 g f y) x
+
+    head (Functor.Pair x _) = head x
+    last (Functor.Pair _ y) = last y
+
+-- | @since 4.18.0.0
+instance (Foldable1 f, Foldable1 g) => Foldable1 (Functor.Sum f g) where
+    foldMap1 f (Functor.InL x) = foldMap1 f x
+    foldMap1 f (Functor.InR y) = foldMap1 f y
+
+    foldrMap1 g f (Functor.InL x) = foldrMap1 g f x
+    foldrMap1 g f (Functor.InR y) = foldrMap1 g f y
+
+    toNonEmpty (Functor.InL x) = toNonEmpty x
+    toNonEmpty (Functor.InR y) = toNonEmpty y
+
+    head (Functor.InL x) = head x
+    head (Functor.InR y) = head y
+    last (Functor.InL x) = last x
+    last (Functor.InR y) = last y
+
+    minimum (Functor.InL x) = minimum x
+    minimum (Functor.InR y) = minimum y
+    maximum (Functor.InL x) = maximum x
+    maximum (Functor.InR y) = maximum y
+
+-- | @since 4.18.0.0
+instance (Foldable1 f, Foldable1 g) => Foldable1 (Compose f g) where
+    foldMap1 f = foldMap1 (foldMap1 f) . getCompose
+
+    foldrMap1 f g = foldrMap1 (foldrMap1 f g) (\xs x -> foldr g x xs) . getCompose
+
+    head = head . head . getCompose
+    last = last . last . getCompose
--- /dev/null
+++ b/lib/Data/Monoid/Internal.hs
@@ -1,0 +1,252 @@
+module Data.Monoid.Internal(module Data.Monoid.Internal) where
+import Prelude()              -- do not import Prelude
+import Primitives
+import Control.Applicative
+import Control.Error
+import Data.Bool
+import Data.Bounded
+import Data.Eq
+import Data.Function
+import Data.Functor
+import Data.Int
+import Data.Integral
+import Data.List_Type
+import Data.List.NonEmpty_Type
+import Data.Ord
+import Data.Maybe_Type
+import Data.Num
+import Text.Show
+
+class Semigroup a => Monoid a where
+  mempty :: a
+  mappend :: a -> a -> a
+  mappend = (<>)
+  mconcat :: [a] -> a
+  mconcat [] = mempty
+  mconcat (a:as) = a <> mconcat as
+
+---------------------
+
+newtype Endo a = Endo (a -> a)
+appEndo :: forall a . Endo a -> (a -> a)
+appEndo (Endo f) = f
+
+instance forall a . Semigroup (Endo a) where
+  Endo f <> Endo g = Endo (f . g)
+
+instance forall a . Monoid (Endo a) where
+  mempty = Endo id
+
+---------------------
+
+newtype Dual a = Dual a
+getDual :: forall a . Dual a -> a
+getDual (Dual a) = a
+
+instance forall a . Semigroup a => Semigroup (Dual a) where
+  Dual a <> Dual b = Dual (b <> a)
+
+instance forall a . Monoid a => Monoid (Dual a) where
+  mempty = Dual mempty
+
+instance Functor Dual where
+  fmap f (Dual a) = Dual (f a)
+
+instance Applicative Dual where
+  pure = Dual
+  Dual f <*> Dual b = Dual (f b)
+
+---------------------
+
+newtype Max a = Max a
+getMax :: forall a . Max a -> a
+getMax (Max a) = a
+
+instance forall a . Ord a => Semigroup (Max a) where
+  Max a <> Max b = Max (a `max` b)
+
+instance forall a . (Ord a, Bounded a) => Monoid (Max a) where
+  mempty = Max minBound
+
+---------------------
+
+newtype Min a = Min a
+getMin :: forall a . Min a -> a
+getMin (Min a) = a
+
+instance forall a . Ord a => Semigroup (Min a) where
+  Min a <> Min b = Min (a `min` b)
+
+instance forall a . (Ord a, Bounded a) => Monoid (Min a) where
+  mempty = Min maxBound
+
+---------------------
+
+newtype Sum a = Sum a
+getSum :: forall a . Sum a -> a
+getSum (Sum a) = a
+
+instance forall a . Num a => Semigroup (Sum a) where
+  Sum a <> Sum b = Sum (a + b)
+
+instance forall a . (Num a) => Monoid (Sum a) where
+  mempty = Sum 0
+
+---------------------
+
+newtype Product a = Product a
+getProduct :: forall a . Product a -> a
+getProduct (Product a) = a
+
+instance forall a . Num a => Semigroup (Product a) where
+  Product a <> Product b = Product (a * b)
+
+instance forall a . (Num a) => Monoid (Product a) where
+  mempty = Product 1
+
+---------------------
+
+newtype All = All Bool
+getAll :: All -> Bool
+getAll (All a) = a
+
+instance Semigroup All where
+  All a <> All b = All (a && b)
+
+instance Monoid All where
+  mempty = All True
+
+---------------------
+
+newtype Any = Any Bool
+getAny :: Any -> Bool
+getAny (Any a) = a
+
+instance Semigroup Any where
+  Any a <> Any b = Any (a || b)
+
+instance Monoid Any where
+  mempty = Any False
+
+---------------------
+
+instance Semigroup Ordering where
+  LT <> _ = LT
+  EQ <> o = o
+  GT <> _ = GT
+
+instance Monoid Ordering where
+  mempty = EQ
+
+----------------------
+
+data Arg a b = Arg a b
+  deriving(Show)
+
+type ArgMin a b = Min (Arg a b)
+
+type ArgMax a b = Max (Arg a b)
+
+instance Functor (Arg a) where
+  fmap f (Arg x a) = Arg x (f a)
+
+instance Eq a => Eq (Arg a b) where
+  Arg a _ == Arg b _ = a == b
+
+instance Ord a => Ord (Arg a b) where
+  Arg a _ `compare` Arg b _ = compare a b
+  min x@(Arg a _) y@(Arg b _)
+    | a <= b    = x
+    | otherwise = y
+  max x@(Arg a _) y@(Arg b _)
+    | a >= b    = x
+    | otherwise = y
+
+----------------------
+
+newtype Alt f a = Alt (f a)
+--  deriving (Show)
+getAlt :: Alt f a -> f a
+getAlt (Alt x) = x
+{-
+  deriving ( Generic     -- ^ @since base-4.8.0.0
+           , Generic1    -- ^ @since base-4.8.0.0
+           , Read        -- ^ @since base-4.8.0.0
+           , Show        -- ^ @since base-4.8.0.0
+           , Eq          -- ^ @since base-4.8.0.0
+           , Ord         -- ^ @since base-4.8.0.0
+           , Num         -- ^ @since base-4.8.0.0
+           , Enum        -- ^ @since base-4.8.0.0
+           , Monad       -- ^ @since base-4.8.0.0
+           , MonadPlus   -- ^ @since base-4.8.0.0
+           , Applicative -- ^ @since base-4.8.0.0
+           , Alternative -- ^ @since base-4.8.0.0
+           , Functor     -- ^ @since base-4.8.0.0
+           )
+-}
+
+instance Alternative f => Semigroup (Alt f a) where
+    Alt x <> Alt y = Alt (x <|> y)
+    stimes = stimesMonoid
+
+instance Alternative f => Monoid (Alt f a) where
+    mempty = Alt empty
+
+----------------------
+
+-- This really belongs in Data.Semigroup,
+-- but some functions have Monoid as in the context.
+
+infixr 6 <>
+class Semigroup a where
+  (<>)    :: a -> a -> a
+  sconcat :: NonEmpty a -> a
+  stimes  :: (Integral b, Ord b) => b -> a -> a
+
+  sconcat (a :| as) = go a as
+    where go b (c:cs) = b <> go c cs
+          go b []     = b
+
+  stimes y0 x0
+    | y0 <= 0   = error "stimes: positive multiplier expected"
+    | otherwise = f x0 y0
+    where
+      f x y
+        | y `rem` 2 == 0 = f (x <> x) (y `quot` 2)
+        | y == 1 = x
+        | otherwise = g (x <> x) (y `quot` 2) x
+      g x y z
+        | y `rem` 2 == 0 = g (x <> x) (y `quot` 2) z
+        | y == 1 = x <> z
+        | otherwise = g (x <> x) (y `quot` 2) (x <> z)
+
+stimesIdempotent :: (Integral b, Ord b) => b -> a -> a
+stimesIdempotent n x =
+  if n <= 0 then error "stimesIdempotent: positive multiplier expected"
+  else x
+
+stimesIdempotentMonoid :: (Ord b, Integral b, Monoid a) => b -> a -> a
+stimesIdempotentMonoid n x = case compare n 0 of
+  LT -> error "stimesIdempotentMonoid: negative multiplier"
+  EQ -> mempty
+  GT -> x
+
+stimesMonoid :: (Ord b, Integral b, Monoid a) => b -> a -> a
+stimesMonoid n x0 = case compare n 0 of
+  LT -> error "stimesMonoid: negative multiplier"
+  EQ -> mempty
+  GT -> f x0 n
+    where
+      f x y
+        | even y = f (x `mappend` x) (y `quot` 2)
+        | y == 1 = x
+        | otherwise = g (x `mappend` x) (y `quot` 2) x
+      g x y z
+        | even y = g (x `mappend` x) (y `quot` 2) z
+        | y == 1 = x `mappend` z
+        | otherwise = g (x `mappend` x) (y `quot` 2) (x `mappend` z)
+
+---------------------
+
+instance (Semigroup b) => Semigroup (a -> b) where
+  f <> g = \ x -> f x <> g x
--