semigroups 0.16.1 → 0.16.2
raw patch · 6 files changed
+180/−9 lines, 6 filesdep ~base
Dependency ranges changed: base
Files
- CHANGELOG.markdown +7/−0
- LICENSE +1/−1
- semigroups.cabal +6/−2
- src/Data/List/NonEmpty.hs +2/−1
- src/Data/Semigroup.hs +82/−5
- src/Data/Semigroup/Generic.hs +82/−0
CHANGELOG.markdown view
@@ -1,3 +1,10 @@+0.16.2+------+* Added `genericMappend` and supporting `GSemigroup` class for generically deriving Semigroup instances.+* Added `Arg a b` which only compares for equality/order on its first argument, which can be used to compute `argmin` and `argmax`.+* Add `Bifunctor` `Arg` instance to avoid orphans for GHC 7.10+.+* Added missing `Data.Monoid.Generic` module to source control.+ 0.16.1 ------ * Added `Semigroup` instances for various Builder constructions in `text` and `bytestring` where available.
LICENSE view
@@ -1,4 +1,4 @@-Copyright 2011-2014 Edward Kmett+Copyright 2011-2015 Edward Kmett All rights reserved.
semigroups.cabal view
@@ -1,6 +1,6 @@ name: semigroups category: Algebra, Data, Data Structures, Math-version: 0.16.1+version: 0.16.2 license: BSD3 cabal-version: >= 1.10 license-file: LICENSE@@ -9,7 +9,7 @@ stability: provisional homepage: http://github.com/ekmett/semigroups/ bug-reports: http://github.com/ekmett/semigroups/issues-copyright: Copyright (C) 2011-2014 Edward A. Kmett+copyright: Copyright (C) 2011-2015 Edward A. Kmett synopsis: Anything that associates description: In mathematics, a semigroup is an algebraic structure consisting of a set together with an associative binary operation. A semigroup generalizes a monoid in that there might not exist an identity element. It also (originally) generalized a group (a monoid with all inverses) to a type where every element did not have to have an inverse, thus the name semigroup.@@ -80,6 +80,10 @@ exposed-modules: Data.Semigroup Data.List.NonEmpty++ if impl(ghc >= 7.4)+ exposed-modules:+ Data.Semigroup.Generic build-depends: base >= 2 && < 5,
src/Data/List/NonEmpty.hs view
@@ -24,7 +24,7 @@ ----------------------------------------------------------------------------- -- | -- Module : Data.List.NonEmpty--- Copyright : (C) 2011-2014 Edward Kmett,+-- Copyright : (C) 2011-2015 Edward Kmett, -- (C) 2010 Tony Morris, Oliver Taylor, Eelis van der Weegen -- License : BSD-style (see the file LICENSE) --@@ -172,6 +172,7 @@ #endif #ifdef LANGUAGE_DeriveGeneric , Generic+ , Generic1 #endif )
src/Data/Semigroup.hs view
@@ -5,7 +5,7 @@ {-# LANGUAGE DeriveDataTypeable #-} #endif -#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702+#if __GLASGOW_HASKELL__ >= 702 #define LANGUAGE_DefaultSignatures {-# LANGUAGE DefaultSignatures #-} #if defined(MIN_VERSION_hashable) || __GLASGOW_HASKELL__ >= 708@@ -15,21 +15,26 @@ #endif #endif -#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 704+#if __GLASGOW_HASKELL__ >= 704 #define LANGUAGE_DeriveGeneric {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE FlexibleContexts #-} #endif --#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 708+#if __GLASGOW_HASKELL__ >= 708 #define USE_COERCE {-# LANGUAGE ScopedTypeVariables #-} #endif +#ifndef MIN_VERSION_base+#define MIN_VERSION_base(x,y,z) 1+#endif+ ----------------------------------------------------------------------------- -- | -- Module : Data.Semigroup--- Copyright : (C) 2011-2014 Edward Kmett+-- Copyright : (C) 2011-2015 Edward Kmett -- License : BSD-style (see the file LICENSE) -- -- Maintainer : Edward Kmett <ekmett@gmail.com>@@ -74,9 +79,18 @@ -- * Difference lists of a semigroup , diff , cycle1+ -- * ArgMin, ArgMax+ , Arg(..)+ , ArgMin+ , ArgMax ) where import Prelude hiding (foldr1)++#if MIN_VERSION_base(4,8,0)+import Data.Bifunctor+#endif+ import Data.Monoid (Monoid(..),Dual(..),Endo(..),All(..),Any(..),Sum(..),Product(..)) import Control.Applicative import Control.Monad@@ -307,6 +321,7 @@ instance Semigroup (NonEmpty a) where (a :| as) <> ~(b :| bs) = a :| (as ++ b : bs) + newtype Min a = Min { getMin :: a } deriving ( Eq, Ord, Show, Read #ifdef LANGUAGE_DeriveDataTypeable@@ -314,6 +329,7 @@ #endif #ifdef LANGUAGE_DeriveGeneric , Generic+ , Generic1 #endif ) @@ -387,6 +403,7 @@ #endif #ifdef LANGUAGE_DeriveGeneric , Generic+ , Generic1 #endif ) @@ -453,6 +470,62 @@ rnf (Max a) = rnf a #endif +-- | 'Arg' isn't itself a 'Semigroup' in its own right, but it can be placed inside 'Min' and 'Max'+-- to compute an arg min or arg max.+data Arg a b = Arg a b deriving+ ( Show, Read+#ifdef LANGUAGE_DeriveDataTypeable+ , Data, Typeable+#endif+#ifdef LANGUAGE_DeriveGeneric+ , Generic+ , Generic1+#endif+ )++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 Foldable (Arg a) where+ foldMap f (Arg _ a) = f a++instance Traversable (Arg a) where+ traverse 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++#ifdef MIN_VERSION_deepseq+instance (NFData a, NFData b) => NFData (Arg a b) where+ rnf (Arg a b) = rnf a `seq` rnf b `seq` ()+#endif++#ifdef MIN_VERSION_hashable+instance (Hashable a, Hashable b) => Hashable (Arg a b) where+#if MIN_VERSION_hashable(1,2,0)+ hashWithSalt p (Arg a b) = hashWithSalt p a `hashWithSalt` b+#else+ hash (Arg a b) = hashWithSalt (hash a) b+#endif+#endif++#if MIN_VERSION_base(4,8,0)+instance Bifunctor Arg where+ bimap f g (Arg a b) = Arg (f a) (g b)+#endif+ -- | Use @'Option' ('First' a)@ to get the behavior of 'Data.Monoid.First' from @Data.Monoid@. newtype First a = First { getFirst :: a } deriving ( Eq, Ord, Show, Read@@ -462,6 +535,7 @@ #endif #ifdef LANGUAGE_DeriveGeneric , Generic+ , Generic1 #endif ) @@ -528,6 +602,7 @@ #endif #ifdef LANGUAGE_DeriveGeneric , Generic+ , Generic1 #endif ) @@ -636,6 +711,7 @@ #endif #ifdef LANGUAGE_DeriveGeneric , Generic+ , Generic1 #endif ) @@ -701,6 +777,7 @@ #endif #ifdef LANGUAGE_DeriveGeneric , Generic+ , Generic1 #endif )
+ src/Data/Semigroup/Generic.hs view
@@ -0,0 +1,82 @@+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE Safe #-}+-----------------------------------------------------------------------------+-- |+-- Module : Data.Semigroup.Generic+-- Copyright : (C) 2014-2015 Edward Kmett, Eric Mertens+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : provisional+-- Portability : portable+--+-- This module provides generic deriving tools for monoids and semigroups for+-- product-like structures.+--+----------------------------------------------------------------------------+module Data.Semigroup.Generic+ ( GSemigroup+ , gmappend+ , GMonoid+ , gmempty+ ) where++import Data.Semigroup+import GHC.Generics++-- | Generically generate a 'Semigroup' ('<>') operation for any type+-- implementing 'Generic'. This operation will append two values+-- by point-wise appending their component fields. It is only defined+-- for product types.+--+-- @+-- 'gmappend' a ('gmappend' b c) = 'gmappend' ('gmappend' a b) c+-- @+gmappend :: (Generic a, GSemigroup (Rep a)) => a -> a -> a+gmappend x y = to (gmappend' (from x) (from y))++class GSemigroup f where+ gmappend' :: f p -> f p -> f p++instance GSemigroup U1 where+ gmappend' _ _ = U1++instance GSemigroup V1 where+ gmappend' x y = x `seq` y `seq` error "GSemigroup.V1: gmappend'"++instance Semigroup a => GSemigroup (K1 i a) where+ gmappend' (K1 x) (K1 y) = K1 (x <> y)++instance GSemigroup f => GSemigroup (M1 i c f) where+ gmappend' (M1 x) (M1 y) = M1 (gmappend' x y)++instance (GSemigroup f, GSemigroup g) => GSemigroup (f :*: g) where+ gmappend' (x1 :*: x2) (y1 :*: y2) = gmappend' x1 y1 :*: gmappend' x2 y2++-- | Generically generate a 'Monoid' 'mempty' for any product-like type+-- implementing 'Generic'.+--+-- It is only defined for product types.+--+-- @+-- 'gmappend' 'gmempty' a = a = 'gmappend' a 'gmempty'+-- @++gmempty :: (Generic a, GMonoid (Rep a)) => a+gmempty = to gmempty'++class GSemigroup f => GMonoid f where+ gmempty' :: f p++instance GMonoid U1 where+ gmempty' = U1++instance (Semigroup a, Monoid a) => GMonoid (K1 i a) where+ gmempty' = K1 mempty++instance GMonoid f => GMonoid (M1 i c f) where+ gmempty' = M1 gmempty'++instance (GMonoid f, GMonoid g) => GMonoid (f :*: g) where+ gmempty' = gmempty' :*: gmempty'