acts 0.2.0.0 → 0.3.0.0
raw patch · 5 files changed
+30/−277 lines, 5 filesdep +groupsdep −generic-dataPVP ok
version bump matches the API change (PVP)
Dependencies added: groups
Dependencies removed: generic-data
API changes (from Hackage documentation)
- Data.Group: (:|:) :: a -> Dual a -> Isom a
- Data.Group: [from] :: Isom a -> Dual a
- Data.Group: [to] :: Isom a -> a
- Data.Group: anti :: Group g => g -> Dual g
- Data.Group: class Monoid g => Group g
- Data.Group: data Isom a
- Data.Group: gtimes :: (Group g, Integral n) => n -> g -> g
- Data.Group: infix 7 :|:
- Data.Group: instance (Data.Group.GGroup f1, Data.Group.GGroup f2) => Data.Group.GGroup (f1 GHC.Generics.:*: f2)
- Data.Group: instance (Data.Group.Group (f1 p), Data.Group.Group (f2 p)) => Data.Group.Group ((GHC.Generics.:*:) f1 f2 p)
- Data.Group: instance (Data.Group.Group a, GHC.Base.Applicative f) => Data.Group.Group (Data.Monoid.Ap f a)
- Data.Group: instance (Data.Group.Group g1, Data.Group.Group g2) => Data.Group.Group (g1, g2)
- Data.Group: instance (Data.Group.Group g1, Data.Group.Group g2, Data.Group.Group g3) => Data.Group.Group (g1, g2, g3)
- Data.Group: instance (Data.Group.Group g1, Data.Group.Group g2, Data.Group.Group g3, Data.Group.Group g4) => Data.Group.Group (g1, g2, g3, g4)
- Data.Group: instance (Data.Group.Group g1, Data.Group.Group g2, Data.Group.Group g3, Data.Group.Group g4, Data.Group.Group g5) => Data.Group.Group (g1, g2, g3, g4, g5)
- Data.Group: instance (GHC.Generics.Generic g, GHC.Base.Monoid (GHC.Generics.Rep g ()), Data.Group.GGroup (GHC.Generics.Rep g)) => Data.Group.Group (Generic.Data.Internal.Generically.Generically g)
- Data.Group: instance (TypeError ...) => Data.Group.GGroup (f1 GHC.Generics.:+: f2)
- Data.Group: instance (TypeError ...) => Data.Group.GGroup GHC.Generics.V1
- Data.Group: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Data.Group.Isom a)
- Data.Group: instance Data.Data.Data a => Data.Data.Data (Data.Group.Isom a)
- Data.Group: instance Data.Group.GGroup GHC.Generics.U1
- Data.Group: instance Data.Group.GGroup f => Data.Group.GGroup (GHC.Generics.M1 i c f)
- Data.Group: instance Data.Group.GGroup f => Data.Group.GGroup (GHC.Generics.Rec1 f)
- Data.Group: instance Data.Group.Group ()
- Data.Group: instance Data.Group.Group (Data.Proxy.Proxy p)
- Data.Group: instance Data.Group.Group (GHC.Generics.U1 p)
- Data.Group: instance Data.Group.Group (f p) => Data.Group.Group (GHC.Generics.M1 i c f p)
- Data.Group: instance Data.Group.Group (f p) => Data.Group.Group (GHC.Generics.Rec1 f p)
- Data.Group: instance Data.Group.Group a => Data.Group.Group (Data.Functor.Const.Const a b)
- Data.Group: instance Data.Group.Group a => Data.Group.Group (Data.Functor.Contravariant.Op a b)
- Data.Group: instance Data.Group.Group a => Data.Group.Group (Data.Functor.Identity.Identity a)
- Data.Group: instance Data.Group.Group a => Data.Group.Group (Data.Ord.Down a)
- Data.Group: instance Data.Group.Group a => Data.Group.Group (Data.Semigroup.Internal.Dual a)
- Data.Group: instance Data.Group.Group a => Data.Group.Group (GHC.ST.ST s a)
- Data.Group: instance Data.Group.Group a => Data.Group.Group (GHC.Types.IO a)
- Data.Group: instance Data.Group.Group a => Data.Group.Group (r -> a)
- Data.Group: instance Data.Group.Group g => Data.Group.GGroup (GHC.Generics.K1 i g)
- Data.Group: instance Data.Group.Group g => Data.Group.Group (GHC.Generics.K1 i g p)
- Data.Group: instance Data.Group.Group g => Data.Group.Group (GHC.Generics.Par1 g)
- Data.Group: instance GHC.Base.Monoid a => Data.Group.Group (Data.Group.Isom a)
- Data.Group: instance GHC.Base.Monoid a => GHC.Base.Monoid (Data.Group.Isom a)
- Data.Group: instance GHC.Base.Semigroup a => GHC.Base.Semigroup (Data.Group.Isom a)
- Data.Group: instance GHC.Generics.Generic (Data.Group.Isom a)
- Data.Group: instance GHC.Generics.Generic1 Data.Group.Isom
- Data.Group: instance GHC.Num.Num a => Data.Group.Group (Data.Semigroup.Internal.Sum a)
- Data.Group: instance GHC.Read.Read a => GHC.Read.Read (Data.Group.Isom a)
- Data.Group: instance GHC.Real.Fractional a => Data.Group.Group (Data.Semigroup.Internal.Product a)
- Data.Group: instance GHC.Show.Show a => GHC.Show.Show (Data.Group.Isom a)
- Data.Group: inverse :: Group g => g -> g
- Data.Group: reflexive :: Dual (Dual a) -> a
+ Data.Act: anti :: Group g => g -> Dual g
- Data.Act: infixr 5 •
+ Data.Act: infixr 5 `act`
Files
- acts.cabal +7/−6
- changelog.md +5/−0
- examples/Acts/Examples/MusicalIntervals.hs +7/−5
- src/Data/Act.hs +11/−5
- src/Data/Group.hs +0/−261
acts.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: acts -version: 0.2.0.0 +version: 0.3.0.0 synopsis: Semigroup actions, groups, and torsors. category: Algebra, Math license: BSD-3-Clause @@ -47,14 +47,12 @@ build-depends: base >= 4.12 && < 4.15 - , deepseq - ^>= 1.4.4.0 , finitary ^>= 1.2.0.0 , finite-typelits ^>= 0.1.4.2 - , generic-data - >= 0.6.0.1 && < 0.7.0.0 + , groups + ^>= 0.4.0.0 default-language: Haskell2010 @@ -78,7 +76,10 @@ exposed-modules: Data.Act - , Data.Group + + build-depends: + deepseq + ^>= 1.4.4.0 library acts-examples
changelog.md view
@@ -1,5 +1,10 @@ # Changelog for package `acts` +## 0.3.0.0 ( February 16, 2020 ) + +* Switch to using the `groups` package for the definition of the `Group` typeclass, +splitting off the generic instances to the `groups-generic` package. + ## 0.2.0.0 ( February 14, 2020 ) * Remove definition of cyclic groups.
examples/Acts/Examples/MusicalIntervals.hs view
@@ -46,11 +46,13 @@ import Data.Finite ( Finite ) +-- groups +import Data.Group + ( Group(..) ) + -- acts import Data.Act ( Act(..), Torsor(..), Finitely(..) ) -import Data.Group - ( Group(..) ) ----------------------------------------------------------------- -- * Musical notes @@ -129,7 +131,7 @@ -- > > Steps ( Sum (-2) ) Natural -- > minor 3rd down -- --- > > inverse ( Steps ( Sum 2 ) Natural ) +-- > > invert ( Steps ( Sum 2 ) Natural ) -- > Steps ( Sum (-2) ) Flat -- > major 3rd down @@ -162,7 +164,7 @@ instance Monoid Interval where mempty = Steps mempty mempty instance Group Interval where - inverse = twist . inverse . straighten + invert = twist . invert . straighten -- | Intervallically correct action of intervals on notes. -- @@ -303,7 +305,7 @@ then ivalName else quality ival <> " " <> ivalName | i < 0 - = quality ( inverse ival ) <> " " <> showOrdinal (-i+1) <> " down" + = quality ( invert ival ) <> " " <> showOrdinal (-i+1) <> " down" | otherwise = quality ival <> " " <> showOrdinal (i+1) <> " up"
src/Data/Act.hs view
@@ -2,13 +2,11 @@ DeriveGeneric , DeriveDataTypeable , DerivingVia - , FlexibleContexts , FlexibleInstances , GeneralizedNewtypeDeriving , MultiParamTypeClasses , ScopedTypeVariables , StandaloneDeriving - , TypeApplications , TypeFamilies , UndecidableInstances #-} @@ -45,6 +43,7 @@ , transportAction , Trivial(..) , Torsor(..) + , anti , intertwiner , Finitely(..) ) @@ -81,9 +80,9 @@ import Data.Finite ( Finite ) --- acts +-- groups import Data.Group - ( Group(..), anti ) + ( Group(..) ) ----------------------------------------------------------------- @@ -235,9 +234,16 @@ infix 7 --> infix 7 <-- +-- | A group's inversion anti-automorphism corresponds to an isomorphism to the opposite group. +-- +-- The inversion allows us to obtain a left action from a right action (of the same group); +-- the equivalent operation is not possible for general semigroups. +anti :: Group g => g -> Dual g +anti g = Dual ( invert g ) + -- | Any group is a torsor under its own natural left action. instance Group g => Torsor g g where - h <-- g = h <> inverse g + h <-- g = h <> invert g instance Num a => Torsor ( Sum a ) a where (<--) = coerce ( (<--) :: Sum a -> Sum a -> Sum a )
− src/Data/Group.hs
@@ -1,261 +0,0 @@-{-# LANGUAGE - DataKinds - , DeriveAnyClass - , DeriveDataTypeable - , DeriveGeneric - , DerivingVia - , GeneralizedNewtypeDeriving - , KindSignatures - , ScopedTypeVariables - , StandaloneDeriving - , TypeApplications - , TypeOperators - , UndecidableInstances -#-} - -{-| -Module: Data.Group - -A 'Group' is a 'Monoid' for which the monoid operation can be undone. - -That is, \( G \) is a group if each \( g \in G \) has an inverse element \( g^{ -1 } \) such that - -\[ g^{ -1 } < \! > g = \text{mempty} = g < \! > g^{ -1 } \] - -Such inverses are necessarily unique. - - -In Haskell, groups are mostly useful to describe objects possessing certain symmetries (such as translation or rotation). - -To automatically derive 'Group' instances, you can: - -- Use @DerivingVia@ to coerce an existing instance: - -> > newtype Seconds = Seconds { getSeconds :: Double } -> > newtype TimeDelta = TimeDelta { timeDeltaInSeconds :: Seconds } -> > deriving ( Semigroup, Monoid, Group ) -> > via Sum Double - -- Use 'Generic' and 'Generic.Data.Generically': - -> > data MyRecord -> > = MyRecord -> > { field1 :: Sum Double -> > , field2 :: Product Double -> > , field3 :: Ap [] ( Sum Int, Sum Int ) -> > } -> > deriving Generic -> > deriving ( Semigroup, Monoid, Group ) -> > via Generically MyRecord --} - - -module Data.Group - ( Group(..), anti, reflexive - , Isom(..) - ) - where - --- base -import Control.Monad.ST - ( ST ) -import Data.Coerce - ( coerce ) -import Data.Data - ( Data ) -import Data.Functor.Const - ( Const(..) ) -import Data.Functor.Contravariant - ( Op(..) ) -import Data.Functor.Identity - ( Identity(..) ) -import Data.Monoid - ( Ap(..), Sum(..), Product(..) ) -import Data.Ord - ( Down(..) ) -import Data.Semigroup - ( Semigroup(..), Dual(..) ) -import Data.Proxy - ( Proxy(..) ) -import GHC.Generics - ( Generic, Generic1 - , U1(..), Rec1(..), M1(..), K1(..), Par1(..), (:*:)(..) - , V1, (:+:) - ) -import qualified GHC.Generics as Generic - ( Generic(..) ) -import GHC.TypeLits - ( TypeError, ErrorMessage(Text) ) - --- deepseq -import Control.DeepSeq - ( NFData ) - --- generic-data -import Generic.Data - ( Generically(..) ) - ------------------------------------------------------------------------ - --- | A 'Group' is a 'Monoid' with inverses: --- --- * @ inverse g <> g = g <> inverse g = mempty @ --- --- * @ inverse (g <> h) = inverse h <> inverse g @ -class Monoid g => Group g where - {-# MINIMAL inverse | gtimes #-} - -- | Group inversion anti-homomorphism. - inverse :: g -> g - inverse = gtimes ( (-1) :: Int ) - - -- | Take the @n@-th power of an element. - gtimes :: Integral n => n -> g -> g - gtimes n = case compare n 0 of - EQ -> const mempty - GT -> stimes n - LT -> stimes ( negate n ) . inverse - --- | The inverse anti-automorphism of a group lifts to a isomorphism with the opposite group. -anti :: Group g => g -> Dual g -anti g = Dual ( inverse g ) - --- | Reflexive property 'Dual' (should be included in base, maybe under another name). -reflexive :: Dual ( Dual a ) -> a -reflexive = coerce - ------------------------------------------------------------------------ --- Instances. - --- | Trivial group. -instance Group () where - inverse _ = () - gtimes _ _ = () - --- | Additive groups (via 'Num'). -instance Num a => Group ( Sum a ) where - inverse ( Sum a ) = Sum ( negate a ) - gtimes n ( Sum a ) = Sum ( fromIntegral n * a ) - --- | Multiplicative group (via 'Num'). -instance Fractional a => Group ( Product a ) where - inverse ( Product a ) = Product ( recip a ) - gtimes n ( Product a ) = Product ( a ^^ toInteger n ) - --- | Opposite group. -instance Group a => Group ( Dual a ) where - inverse ( Dual a ) = Dual ( inverse a ) - gtimes n ( Dual a ) = Dual ( gtimes n a ) - --- | Lifting group operations through an applicative functor. -instance ( Group a, Applicative f ) => Group ( Ap f a ) where - inverse = fmap inverse - gtimes n = fmap ( gtimes n ) - -deriving via Ap ((->) r) a instance Group a => Group ( r -> a ) -deriving via Ap IO a instance Group a => Group ( IO a ) -deriving via Ap (ST s) a instance Group a => Group ( ST s a ) - -deriving newtype instance Group a => Group ( Down a ) -deriving newtype instance Group a => Group ( Identity a ) -deriving newtype instance Group a => Group ( Const a b ) -deriving newtype instance Group a => Group ( Op a b ) - -instance Group ( Proxy p ) where - inverse _ = Proxy - gtimes _ _ = Proxy - -instance ( Group g1, Group g2 ) - => Group ( g1, g2 ) where - inverse ( g1, g2 ) = - ( inverse g1, inverse g2 ) - gtimes n ( g1, g2 ) = - ( gtimes n g1, gtimes n g2 ) - -instance ( Group g1, Group g2, Group g3 ) - => Group ( g1, g2, g3 ) where - inverse ( g1, g2, g3 ) = - ( inverse g1, inverse g2, inverse g3 ) - gtimes n ( g1, g2, g3 ) = - ( gtimes n g1, gtimes n g2, gtimes n g3 ) - -instance ( Group g1, Group g2, Group g3, Group g4 ) - => Group ( g1, g2, g3, g4 ) where - inverse ( g1, g2, g3, g4 ) = - ( inverse g1, inverse g2, inverse g3, inverse g4 ) - gtimes n ( g1, g2, g3, g4 ) = - ( gtimes n g1, gtimes n g2, gtimes n g3, gtimes n g4 ) - -instance ( Group g1, Group g2, Group g3, Group g4, Group g5 ) - => Group ( g1, g2, g3, g4, g5 ) where - inverse ( g1, g2, g3, g4, g5 ) = - ( inverse g1, inverse g2, inverse g3, inverse g4, inverse g5 ) - gtimes n ( g1, g2, g3, g4, g5 ) = - ( gtimes n g1, gtimes n g2, gtimes n g3, gtimes n g4, gtimes n g5 ) - -infix 7 :|: --- | Data type to keep track of a pair of inverse elements. -data Isom a = (:|:) { to :: a, from :: Dual a } - deriving stock ( Show, Read, Data, Generic, Generic1 ) - deriving anyclass NFData -instance Semigroup a => Semigroup ( Isom a ) where - ( p1 :|: q1 ) <> ( p2 :|: q2 ) = ( p1 <> p2 ) :|: ( q1 <> q2 ) -instance Monoid a => Monoid ( Isom a ) where - mempty = mempty :|: mempty -instance Monoid a => Group ( Isom a ) where - inverse ( p :|: q ) = getDual q :|: Dual p - --- Generics. - -instance Group ( U1 p ) where - inverse _ = U1 - gtimes _ _ = U1 - -deriving newtype instance Group ( f p ) => Group ( Rec1 f p ) -deriving newtype instance Group ( f p ) => Group ( M1 i c f p ) -deriving newtype instance Group g => Group ( K1 i g p ) -deriving newtype instance Group g => Group ( Par1 g ) - -instance ( Group ( f1 p ), Group ( f2 p ) ) => Group ( (f1 :*: f2) p ) where - inverse ( g1 :*: g2 ) = ( inverse g1 :*: inverse g2 ) - gtimes n ( g1 :*: g2 ) = ( gtimes n g1 :*: gtimes n g2 ) - -instance - ( Generic g - , Monoid ( Generic.Rep g () ) - , GGroup ( Generic.Rep g ) - ) - => Group ( Generically g ) where - inverse = Generically . Generic.to . ginverse . Generic.from . unGenerically - gtimes n = Generically . Generic.to . ggtimes n . Generic.from . unGenerically - --- | Type class used for deriving 'Group' instances generically. -class GGroup f where - ginverse :: f p -> f p - ggtimes :: Integral n => n -> f p -> f p - -instance GGroup U1 where - ginverse _ = U1 - ggtimes _ _ = U1 - -deriving newtype instance GGroup f => GGroup ( Rec1 f ) -deriving newtype instance GGroup f => GGroup ( M1 i c f ) - -instance Group g => GGroup ( K1 i g ) where - ginverse ( K1 g ) = K1 ( inverse g ) - ggtimes n ( K1 g ) = K1 ( gtimes n g ) - -instance ( GGroup f1, GGroup f2 ) => GGroup ( f1 :*: f2 ) where - ginverse ( g1 :*: g2 ) = ( ginverse g1 :*: ginverse g2 ) - ggtimes n ( g1 :*: g2 ) = ( ggtimes n g1 :*: ggtimes n g2 ) - -instance - TypeError ( 'Text "No 'Group' instance for empty generic representation." ) - => GGroup V1 where - ginverse _ = error "unreachable" - ggtimes _ _ = error "unreachable" - -instance - TypeError ( 'Text "No 'Group' instance for generic sum type." ) - => GGroup ( f1 :+: f2 ) where - ginverse _ = error "unreachable" - ggtimes _ _ = error "unreachable"