acts 0.1.0.0 → 0.2.0.0
raw patch · 6 files changed
+114/−199 lines, 6 filesdep +finitaryPVP ok
version bump matches the API change (PVP)
Dependencies added: finitary
API changes (from Hackage documentation)
- Data.Act: instance (Data.Act.Act g x, Data.Group.Group g) => Data.Act.Act (Data.Semigroup.Internal.Dual g) x
- Data.Act: instance GHC.Classes.Ord a => Data.Act.Act (Data.Semigroup.Max a) a
- Data.Act: instance GHC.Classes.Ord a => Data.Act.Act (Data.Semigroup.Min a) a
- Data.Group.Cyclic: CyclicEnum :: a -> CyclicEnum a
- Data.Group.Cyclic: [getCyclicEnum] :: CyclicEnum a -> a
- Data.Group.Cyclic: data Cyclic n
- Data.Group.Cyclic: getCyclic :: forall n. KnownNat n => Cyclic n -> Int
- Data.Group.Cyclic: instance (GHC.Enum.Enum a, GHC.Enum.Bounded a, GHC.TypeNats.KnownNat n) => Data.Act.Act (Data.Group.Cyclic.Cyclic n) (Data.Group.Cyclic.CyclicEnum a)
- Data.Group.Cyclic: instance (GHC.Enum.Enum a, GHC.Enum.Bounded a, GHC.TypeNats.KnownNat n, 1 GHC.TypeNats.<= n) => Data.Act.Torsor (Data.Group.Cyclic.Cyclic n) (Data.Group.Cyclic.CyclicEnum a)
- Data.Group.Cyclic: instance (GHC.TypeNats.KnownNat n, 1 GHC.TypeNats.<= n) => Data.Group.Group (Data.Group.Cyclic.Cyclic n)
- Data.Group.Cyclic: instance (GHC.TypeNats.KnownNat n, 1 GHC.TypeNats.<= n) => GHC.Base.Monoid (Data.Group.Cyclic.Cyclic n)
- Data.Group.Cyclic: instance Control.DeepSeq.NFData (Data.Group.Cyclic.Cyclic n)
- Data.Group.Cyclic: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Data.Group.Cyclic.CyclicEnum a)
- Data.Group.Cyclic: instance Data.Act.Act (Data.Group.Cyclic.Cyclic 2) GHC.Types.Bool
- Data.Group.Cyclic: instance Data.Data.Data a => Data.Data.Data (Data.Group.Cyclic.CyclicEnum a)
- Data.Group.Cyclic: instance GHC.Classes.Eq (Data.Group.Cyclic.Cyclic n)
- Data.Group.Cyclic: instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.Group.Cyclic.CyclicEnum a)
- Data.Group.Cyclic: instance GHC.Classes.Ord (Data.Group.Cyclic.Cyclic n)
- Data.Group.Cyclic: instance GHC.Classes.Ord a => GHC.Classes.Ord (Data.Group.Cyclic.CyclicEnum a)
- Data.Group.Cyclic: instance GHC.Enum.Bounded a => GHC.Enum.Bounded (Data.Group.Cyclic.CyclicEnum a)
- Data.Group.Cyclic: instance GHC.Enum.Enum a => GHC.Enum.Enum (Data.Group.Cyclic.CyclicEnum a)
- Data.Group.Cyclic: instance GHC.Generics.Generic (Data.Group.Cyclic.Cyclic n)
- Data.Group.Cyclic: instance GHC.Generics.Generic (Data.Group.Cyclic.CyclicEnum a)
- Data.Group.Cyclic: instance GHC.Generics.Generic1 Data.Group.Cyclic.Cyclic
- Data.Group.Cyclic: instance GHC.Generics.Generic1 Data.Group.Cyclic.CyclicEnum
- Data.Group.Cyclic: instance GHC.Num.Num a => Data.Act.Act (Data.Group.Cyclic.Cyclic 2) (Data.Complex.Complex a)
- Data.Group.Cyclic: instance GHC.Num.Num i => Data.Act.Act (Data.Group.Cyclic.Cyclic 2) (Data.Semigroup.Internal.Sum i)
- Data.Group.Cyclic: instance GHC.Real.Fractional i => Data.Act.Act (Data.Group.Cyclic.Cyclic 2) (Data.Semigroup.Internal.Product i)
- Data.Group.Cyclic: instance GHC.Show.Show (Data.Group.Cyclic.Cyclic n)
- Data.Group.Cyclic: instance GHC.Show.Show a => GHC.Show.Show (Data.Group.Cyclic.CyclicEnum a)
- Data.Group.Cyclic: instance GHC.TypeNats.KnownNat n => Data.Act.Act (Data.Group.Cyclic.Cyclic n) GHC.Types.Int
- Data.Group.Cyclic: instance GHC.TypeNats.KnownNat n => GHC.Base.Semigroup (Data.Group.Cyclic.Cyclic n)
- Data.Group.Cyclic: instance GHC.TypeNats.KnownNat n => GHC.Enum.Bounded (Data.Group.Cyclic.Cyclic n)
- Data.Group.Cyclic: instance GHC.TypeNats.KnownNat n => GHC.Enum.Enum (Data.Group.Cyclic.Cyclic n)
- Data.Group.Cyclic: involution :: Act (Cyclic 2) x => x -> x
- Data.Group.Cyclic: newtype CyclicEnum a
- Data.Group.Cyclic: pattern Cyclic :: forall n. KnownNat n => Int -> Cyclic n
- Data.Group.Cyclic: pattern Involution :: Cyclic 2
- Data.Group.Cyclic: rootOfUnity :: forall a n. (KnownNat n, Floating a) => Cyclic n -> Complex a
- Data.Group.Cyclic: type C (n :: Nat) = Cyclic n
- Data.Group.Cyclic: type Z = Sum Int
+ Data.Act: Finitely :: a -> Finitely a
+ Data.Act: [getFinitely] :: Finitely a -> a
+ Data.Act: instance (Data.Group.Group g, Data.Act.Torsor g (Data.Finite.Internal.Finite n), Data.Finitary.Finitary a, n GHC.Types.~ Data.Finitary.Cardinality a) => Data.Act.Torsor g (Data.Act.Finitely a)
+ Data.Act: instance (GHC.Base.Semigroup s, Data.Act.Act s (Data.Finite.Internal.Finite n), Data.Finitary.Finitary a, n GHC.Types.~ Data.Finitary.Cardinality a) => Data.Act.Act s (Data.Act.Finitely a)
+ Data.Act: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Data.Act.Finitely a)
+ Data.Act: instance Data.Data.Data a => Data.Data.Data (Data.Act.Finitely a)
+ Data.Act: instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.Act.Finitely a)
+ Data.Act: instance GHC.Classes.Ord a => GHC.Classes.Ord (Data.Act.Finitely a)
+ Data.Act: instance GHC.Generics.Generic (Data.Act.Finitely a)
+ Data.Act: instance GHC.Generics.Generic1 Data.Act.Finitely
+ Data.Act: instance GHC.Read.Read a => GHC.Read.Read (Data.Act.Finitely a)
+ Data.Act: instance GHC.Show.Show a => GHC.Show.Show (Data.Act.Finitely a)
+ Data.Act: newtype Finitely a
+ Data.Group: anti :: Group g => g -> Dual g
+ Data.Group: reflexive :: Dual (Dual a) -> a
Files
- acts.cabal +3/−2
- changelog.md +18/−1
- examples/Acts/Examples/MusicalIntervals.hs +24/−7
- src/Data/Act.hs +58/−13
- src/Data/Group.hs +11/−1
- src/Data/Group/Cyclic.hs +0/−175
acts.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: acts -version: 0.1.0.0 +version: 0.2.0.0 synopsis: Semigroup actions, groups, and torsors. category: Algebra, Math license: BSD-3-Clause @@ -49,6 +49,8 @@ >= 4.12 && < 4.15 , deepseq ^>= 1.4.4.0 + , finitary + ^>= 1.2.0.0 , finite-typelits ^>= 0.1.4.2 , generic-data @@ -77,7 +79,6 @@ exposed-modules: Data.Act , Data.Group - , Data.Group.Cyclic library acts-examples
changelog.md view
@@ -1,5 +1,22 @@ # Changelog for package `acts` -## 0.1.0.0 ( February 2020 ) +## 0.2.0.0 ( February 14, 2020 ) + +* Remove definition of cyclic groups. +It is instead suggested to use a library which defines modular arithmetic. +For instance: `type C (n :: Nat) = Sum ( Finite n )`, using the `finite-typelits` library. + +* `CyclicEnum` newtype changed to `Finitely` newtype, which uses `Finitary` instead of `Bounded + Enum`. +This ensures that the action is by a semigroup of the right cardinality. + +* Remove `Act` instances for `Max`, `Min` to avoid possible overlap with user defined instances. + +* Add `anti :: Group g => g -> Dual g` function to construct elements in the opposite _group_. +Obsoletes the `Act` instance for `Dual` (now removed). + +* Address a limitation of GHC < 8.10 with `DerivingVia` and `MultiParamTypeClasses`, +by manually writing some instances. + +## 0.1.0.0 ( February 13, 2020 ) * Initial release.
examples/Acts/Examples/MusicalIntervals.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE DataKinds + , DeriveAnyClass , DeriveGeneric , DerivingVia , MultiParamTypeClasses @@ -34,11 +35,22 @@ -- base import Data.Monoid ( Sum(..) ) +import GHC.Generics + ( Generic ) +-- finitary +import Data.Finitary + ( Finitary ) + +-- finite-typelits +import Data.Finite + ( Finite ) + -- acts import Data.Act + ( Act(..), Torsor(..), Finitely(..) ) import Data.Group -import Data.Group.Cyclic + ( Group(..) ) ----------------------------------------------------------------- -- * Musical notes @@ -46,17 +58,21 @@ -- $notenames -- We begin by defining note names, which are acted upon by the cyclic group of order 7. +-- | Cyclic group of order 7. +type C7 = Sum ( Finite 7 ) + -- | Musical note names. -- -- The enumeration starts with @C@ to conform with scientific pitch notation. data NoteName = C | D | E | F | G | A | B - deriving stock ( Eq, Ord, Show, Enum, Bounded ) - deriving ( Act ( C 7 ), Torsor ( C 7 ) ) - via CyclicEnum NoteName + deriving stock ( Eq, Ord, Show, Enum, Bounded, Generic ) + deriving anyclass Finitary + deriving ( Act C7, Torsor C7 ) + via Finitely NoteName -- $deriving1 --- In this case we used @DerivingVia@ to derive the action of @C 7@, --- using the 'CyclicEnum' newtype created for this exact purpose. +-- In this case we used @DerivingVia@ to derive the action of @C7@ +-- through the 'Finitary' instance of 'NoteName' by using the 'Finitely' newtype. -- | Alterations, i.e. sharps and flats. -- @@ -153,8 +169,9 @@ -- * minor third up from @C@: @Eb@ -- * minor third up from @A@: @C@. instance Act Interval Note where - act ( Steps ( Sum steps ) a ) ( Note C a' o ) = Note ( act ( Cyclic @7 r ) C ) ( a <> a' ) ( q + o ) + act ( Steps ( Sum steps ) a ) ( Note C a' o ) = Note ( act ( fromIntegral r :: C7 ) C ) ( a <> a' ) ( q + o ) where + q, r :: Int ( q, r ) = steps `divMod` 7 act ival note = act ( ival <> ( Note C Natural 0 --> note ) ) ( Note C Natural 0 )
src/Data/Act.hs view
@@ -8,6 +8,8 @@ , MultiParamTypeClasses , ScopedTypeVariables , StandaloneDeriving + , TypeApplications + , TypeFamilies , UndecidableInstances #-} @@ -44,6 +46,7 @@ , Trivial(..) , Torsor(..) , intertwiner + , Finitely(..) ) where @@ -62,7 +65,7 @@ , Ap(..), Endo(..) ) import Data.Semigroup - ( Max(..), Min(..), Dual(..) ) + ( Dual(..) ) import GHC.Generics ( Generic, Generic1 ) @@ -70,9 +73,17 @@ import Control.DeepSeq ( NFData ) +-- finitary +import Data.Finitary + ( Finitary(..) ) + +-- finite-typelits +import Data.Finite + ( Finite ) + -- acts import Data.Group - ( Group(..) ) + ( Group(..), anti ) ----------------------------------------------------------------- @@ -118,10 +129,10 @@ deriving via Any instance Act Any Bool deriving via All instance Act All Bool -deriving via ( Sum a ) instance Num a => Act ( Sum a ) a -deriving via ( Product a ) instance Num a => Act ( Product a ) a -deriving via ( Max a ) instance Ord a => Act ( Max a ) a -deriving via ( Min a ) instance Ord a => Act ( Min a ) a +instance Num a => Act ( Sum a ) a where + act s = coerce ( act s :: Sum a -> Sum a ) +instance Num a => Act ( Product a ) a where + act s = coerce ( act s :: Product a -> Product a ) instance {-# OVERLAPPING #-} Act () x where act _ = id @@ -148,22 +159,55 @@ instance ( Act s x, Functor f ) => Act s ( Ap f x ) where act s = coerce ( fmap ( act s ) :: f x -> f x ) --- | Acting through the contravariant function arrow functor. +-- | Acting through the contravariant function arrow functor: right action. +-- +-- If acting by a group, use `anti :: Group g => g -> Dual g` to act by the original group +-- instead of the opposite group. instance ( Semigroup s, Act s a ) => Act ( Dual s ) ( Op b a ) where act ( Dual s ) = coerce ( ( . act s ) :: ( a -> b ) -> ( a -> b ) ) -- | Acting through a function arrow: both covariant and contravariant actions. +-- +-- If acting by a group, use `anti :: Group g => g -> Dual g` to act by the original group +-- instead of the opposite group. instance ( Semigroup s, Act s a, Act t b ) => Act ( Dual s, t ) ( a -> b ) where act ( Dual s, t ) p = act t . p . act s --- | Action of an opposite group using inverses. -instance {-# OVERLAPPABLE #-} ( Act g x, Group g ) => Act ( Dual g ) x where - act ( Dual g ) = act ( inverse g ) - -- | Action of a group on endomorphisms. instance ( Group g, Act g a ) => Act g ( Endo a ) where - act g = coerce ( act ( Dual g, g ) :: ( a -> a ) -> ( a -> a ) ) + act g = coerce ( act ( anti g, g ) :: ( a -> a ) -> ( a -> a ) ) +-- | Newtype for the action on a type through its 'Finitary' instance. +-- +-- > data ABCD = A | B | C | D +-- > deriving stock ( Eq, Generic ) +-- > deriving anyclass Finitary +-- > deriving ( Act ( Sum ( Finite 4 ) ), Torsor ( Sum ( Finite 4 ) ) ) +-- > via Finitely ABCD +-- +-- Sizes are checked statically. For instance if we had instead written: +-- +-- > deriving ( Act ( Sum ( Finite 3 ) ), Torsor ( Sum ( Finite 3 ) ) ) +-- > via Finitely ABCD +-- +-- we would have gotten the error messages: +-- +-- > * No instance for (Act (Sum (Finite 3)) (Finite 4)) +-- > * No instance for (Torsor (Sum (Finite 3)) (Finite 4)) +-- +newtype Finitely a = Finitely { getFinitely :: a } + deriving stock ( Show, Read, Data, Generic, Generic1 ) + deriving newtype ( Eq, Ord, NFData ) + +-- | Act on a type through its 'Finitary' instance. +instance ( Semigroup s, Act s ( Finite n ), Finitary a, n ~ Cardinality a ) + => Act s ( Finitely a ) where + act s = Finitely . fromFinite . act s . toFinite . getFinitely +-- | Torsor for a type using its 'Finitary' instance. +instance ( Group g, Torsor g ( Finite n ), Finitary a, n ~ Cardinality a ) + => Torsor g ( Finitely a ) where + Finitely x --> Finitely y = toFinite x --> toFinite y + ----------------------------------------------------------------- -- | A left __torsor__ consists of a /free/ and /transitive/ left action of a group on an inhabited type. @@ -195,7 +239,8 @@ instance Group g => Torsor g g where h <-- g = h <> inverse g -deriving via ( Sum a ) instance Num a => Torsor ( Sum a ) a +instance Num a => Torsor ( Sum a ) a where + (<--) = coerce ( (<--) :: Sum a -> Sum a -> Sum a ) -- | Given --
src/Data/Group.hs view
@@ -51,7 +51,7 @@ module Data.Group - ( Group(..) + ( Group(..), anti, reflexive , Isom(..) ) where @@ -59,6 +59,8 @@ -- base import Control.Monad.ST ( ST ) +import Data.Coerce + ( coerce ) import Data.Data ( Data ) import Data.Functor.Const @@ -112,6 +114,14 @@ 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.
− src/Data/Group/Cyclic.hs
@@ -1,175 +0,0 @@-{-# LANGUAGE - DataKinds - , DeriveDataTypeable - , DeriveGeneric - , DerivingVia - , FlexibleContexts - , FlexibleInstances - , GADTs - , GeneralizedNewtypeDeriving - , MultiParamTypeClasses - , PatternSynonyms - , PolyKinds - , ScopedTypeVariables - , StandaloneDeriving - , TypeApplications - , TypeFamilies - , TypeOperators - , ViewPatterns -#-} - -{-| -Module: Data.Group.Cyclic - -Cyclic groups: integers modulo @n@ (clock arithmetic). --} - -module Data.Group.Cyclic - ( Cyclic(Cyclic), getCyclic - , C, Z - , CyclicEnum(..) - , pattern Involution, involution - , rootOfUnity - ) - where - --- base -import Data.Coerce - ( coerce ) -import Data.Complex - ( Complex(..), conjugate, mkPolar ) -import Data.Data - ( Data ) -import Data.Monoid - ( Sum(..), Product(..) ) -import Data.Proxy - ( Proxy(..) ) -import GHC.Generics - ( Generic, Generic1 ) -import GHC.TypeNats - ( Nat, KnownNat, natVal - , type (<=) - ) - --- deepseq -import Control.DeepSeq - ( NFData ) - --- finite-typelits -import Data.Finite - ( Finite, getFinite ) - --- acts -import Data.Act - ( Act(..), Torsor(..) ) -import Data.Group - ( Group(..) ) - ------------------------------------------------------------------ - --- | Cyclic group of order @n@: integers with addition modulo @n@. -newtype Cyclic n = MkCyclic { runCyclic :: Finite n } - deriving stock ( Show, Generic, Generic1 ) - deriving newtype ( Eq, Ord, Enum, Bounded, NFData ) -deriving via ( Sum ( Finite n ) ) instance KnownNat n => Semigroup ( Cyclic n ) -deriving via ( Sum ( Finite n ) ) instance ( KnownNat n, 1 <= n ) => Monoid ( Cyclic n ) -deriving via ( Sum ( Finite n ) ) instance ( KnownNat n, 1 <= n ) => Group ( Cyclic n ) - -{-# COMPLETE Cyclic #-} --- | Smart pattern and constructor for elements of cyclic groups. -pattern Cyclic :: forall n. KnownNat n => Int -> Cyclic n -pattern Cyclic i <- ( fromIntegral . getFinite . runCyclic -> i ) - where - Cyclic i = MkCyclic ( fromIntegral ( i `mod` ( fromIntegral ( natVal ( Proxy @n ) ) ) ) ) - --- | Obtain a representative in the range \( [0, n[ \). -getCyclic :: forall n. KnownNat n => Cyclic n -> Int -getCyclic ( Cyclic i ) = i - --- | Synonym for finite cyclic group. -type C ( n :: Nat ) = Cyclic n --- | Synonym for infinite cyclic group. -type Z = Sum Int - -instance KnownNat n => Act ( Cyclic n ) Int where - act ( Cyclic f ) j - | r + i >= n - = ( i - n ) + j - | otherwise - = i + j - where - i, n, r :: Int - i = fromIntegral f - n = fromIntegral ( natVal ( Proxy @n ) ) - r = j `mod` n - --- | Nontrivial element of cyclic group of order 2. -pattern Involution :: Cyclic 2 -pattern Involution = Cyclic 1 - --- | Act by an involution. -involution :: Act ( Cyclic 2 ) x => x -> x -involution = act Involution - -instance Act ( Cyclic 2 ) Bool where - act Involution = not - act _ = id - -instance Num i => Act ( Cyclic 2 ) ( Sum i ) where - act Involution = coerce ( negate :: i -> i ) - act _ = id - -instance Fractional i => Act ( Cyclic 2 ) ( Product i ) where - act Involution = coerce ( recip :: i -> i ) - act _ = id - -instance Num a => Act ( Cyclic 2 ) ( Complex a ) where - act Involution = conjugate - act _ = id - --- | Natural complex representations of finite cyclic groups as roots of unity. -rootOfUnity :: forall a n. ( KnownNat n, Floating a ) => Cyclic n -> Complex a -rootOfUnity ( Cyclic f ) = mkPolar 1 ( 2 * pi * i / n ) - where - i, n :: a - i = fromIntegral f - n = fromIntegral ( natVal ( Proxy @n ) ) - --- | Newtype for cycling through elements in a finite enumeration. --- --- > data ABCD = A | B | C | D --- > deriving stock ( Enum, Bounded ) --- > deriving ( Act ( Cyclic 4 ), Torsor ( Cyclic 4 ) ) --- > via CyclicEnum ABCD --- --- > > act ( Cyclic 2 ) C --- > A --- --- > > act ( Cyclic (-1) ) A --- > D --- --- > > ( C --> B :: Cyclic 4 ) --- > Cyclic 3 --- --- __Warning__ --- It is unfortunately not checked that the size of the group --- matches the size of the finite enumeration. --- Please manually ensure this condition. -newtype CyclicEnum a = CyclicEnum { getCyclicEnum :: a } - deriving stock ( Show, Data, Generic, Generic1 ) - deriving newtype ( Eq, Ord, Enum, Bounded, NFData ) - -instance ( Enum a, Bounded a, KnownNat n ) => Act ( Cyclic n ) ( CyclicEnum a ) where - act ( Cyclic f ) a = toEnum j - where - b_min, b_max, i, j :: Int - b_min = fromEnum ( minBound @a ) - b_max = fromEnum ( maxBound @a ) - i = fromIntegral f - j = b_min + ( fromEnum a + i - b_min ) `mod` ( 1 + b_max - b_min ) - -- Assumes n ~ ( 1 + b_max - b_min ). -instance ( Enum a, Bounded a, KnownNat n, 1 <= n ) => Torsor ( Cyclic n ) ( CyclicEnum a ) where - a --> b = Cyclic . fromIntegral . ( `mod` n ) $ fromEnum b - fromEnum a - where - n :: Int - n = fromIntegral ( natVal ( Proxy @n ) )