Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

## Unreleased

* Stop defining `Group`; `Group` from the `groups` package can be used instead.

Most of the instances are provided by `groups`, except the `Group
MonoidalMap` instance, which is not lawful. `reflex` might provide it as an
orphan for backwards compat, temporarily, but it should eventually be removed
everywhere.

* Add support for GHC 9.8 and 9.10

* Replace partial `Map.lookup` with proper custom error for internal error.
Expand Down
6 changes: 2 additions & 4 deletions patch.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,11 @@ library
if flag(split-these)
build-depends:
these >=1 && <1.3,
semialign >=1 && <1.4,
monoidal-containers >=0.6 && <0.7
semialign >=1 && <1.4

else
build-depends:
these >=0.4 && <0.9,
monoidal-containers ==0.4.0.0
these >=0.4 && <0.9

test-suite tests
type: exitcode-stdio-1.0
Expand Down
62 changes: 1 addition & 61 deletions src/Data/Patch.hs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}

Expand All @@ -13,22 +11,11 @@ module Data.Patch
, module X
) where

import Data.Semigroup.Commutative
import Data.Functor.Const (Const (..))
import Data.Functor.Identity
import Data.Map.Monoidal (MonoidalMap)
import Data.Proxy
import GHC.Generics

#if !MIN_VERSION_base(4,18,0)
import Control.Applicative (liftA2)
#endif

#if !MIN_VERSION_base(4,11,0)
import Data.Semigroup (Semigroup (..))
#endif

import qualified Data.Semigroup.Commutative as X
import Data.Semigroup.Commutative as X
import Data.Patch.Class as X
import Data.Patch.DMap as X hiding (getDeletions)
import Data.Patch.DMapWithMove as X
Expand All @@ -45,56 +32,9 @@ import Data.Patch.MapWithMove as X
, unsafePatchMapWithMove
)

-- | A 'Group' is a 'Monoid' where every element has an inverse.
class (Semigroup q, Monoid q) => Group q where
negateG :: q -> q
(~~) :: q -> q -> q
r ~~ s = r <> negateG s

-- | The elements of an 'Commutative' 'Semigroup' can be considered as patches of their own type.
newtype AdditivePatch p = AdditivePatch { unAdditivePatch :: p }

instance Commutative p => Patch (AdditivePatch p) where
type PatchTarget (AdditivePatch p) = p
apply (AdditivePatch p) q = Just $ p <> q

instance (Ord k, Group q) => Group (MonoidalMap k q) where
negateG = fmap negateG

-- | Trivial group.
instance Group () where
negateG _ = ()
_ ~~ _ = ()

-- | Product group. A Pair of groups gives rise to a group
instance (Group a, Group b) => Group (a, b) where
negateG (a, b) = (negateG a, negateG b)
(a, b) ~~ (c, d) = (a ~~ c, b ~~ d)

-- See https://gitlab.haskell.org/ghc/ghc/issues/11135#note_111802 for the reason Compose is not also provided.
-- Base does not define Monoid (Compose f g a) so this is the best we can
-- really do for functor composition.
instance Group (f (g a)) => Group ((f :.: g) a) where
negateG (Comp1 xs) = Comp1 (negateG xs)
Comp1 xs ~~ Comp1 ys = Comp1 (xs ~~ ys)

-- | Product of groups, Functor style.
instance (Group (f a), Group (g a)) => Group ((f :*: g) a) where
negateG (a :*: b) = negateG a :*: negateG b
(a :*: b) ~~ (c :*: d) = (a ~~ c) :*: (b ~~ d)

-- | Trivial group, Functor style
instance Group (Proxy x) where
negateG _ = Proxy
_ ~~ _ = Proxy

-- | Const lifts groups into a functor.
deriving instance Group a => Group (Const a x)

-- | Identity lifts groups pointwise (at only one point)
deriving instance Group a => Group (Identity a)

-- | Functions lift groups pointwise.
instance Group b => Group (a -> b) where
negateG f = negateG . f
(~~) = liftA2 (~~)