Skip to content

Commit fafce08

Browse files
authored
Merge pull request #34 from reflex-frp/patchable
Add `PatchOrReplacement`
2 parents e548892 + b1153c6 commit fafce08

File tree

3 files changed

+67
-0
lines changed

3 files changed

+67
-0
lines changed

ChangeLog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
## Unreleased
44

5+
* Add `PatchOrReplacement`, patch which either is some other patch type or a
6+
new replacement value.
7+
58
* Support GHC 9.2
69

710
## 0.0.5.2 - 2022-01-09

patch.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ library
5757
, Data.Patch.Map
5858
, Data.Patch.MapWithMove
5959
, Data.Patch.MapWithPatchingMove
60+
, Data.Patch.PatchOrReplacement
6061
, Data.Semigroup.Additive
6162

6263
ghc-options: -Wall -fwarn-redundant-constraints -fwarn-tabs

src/Data/Patch/PatchOrReplacement.hs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{-# LANGUAGE CPP #-}
2+
{-# LANGUAGE DeriveGeneric #-}
3+
{-# LANGUAGE FlexibleContexts #-}
4+
{-# LANGUAGE FlexibleInstances #-}
5+
{-# LANGUAGE LambdaCase #-}
6+
{-# LANGUAGE StandaloneDeriving #-}
7+
{-# LANGUAGE TypeFamilies #-}
8+
{-# LANGUAGE UndecidableInstances #-}
9+
10+
module Data.Patch.PatchOrReplacement where
11+
12+
import Data.Patch
13+
#if !MIN_VERSION_base(4,11,0)
14+
import Data.Semigroup (Semigroup (..))
15+
#endif
16+
import GHC.Generics
17+
18+
-- | Either a patch or a replacement value.
19+
--
20+
-- A good patch type will describe small changes very efficiently, but
21+
-- that often comes at the cost of describing large change rather
22+
-- inefficiently. 'PatchOrReplacement' can be used as an escape hatch:
23+
-- when the change as a patch would be too big, just provide a new value
24+
-- to replace the old one with instead.
25+
--
26+
-- @since 0.0.6
27+
data PatchOrReplacement p
28+
= PatchOrReplacement_Patch p
29+
| PatchOrReplacement_Replacement (PatchTarget p)
30+
deriving (Generic)
31+
32+
deriving instance (Eq p, Eq (PatchTarget p)) => Eq (PatchOrReplacement p)
33+
deriving instance (Ord p, Ord (PatchTarget p)) => Ord (PatchOrReplacement p)
34+
deriving instance (Show p, Show (PatchTarget p)) => Show (PatchOrReplacement p)
35+
deriving instance (Read p, Read (PatchTarget p)) => Read (PatchOrReplacement p)
36+
37+
completePatchOrReplacement :: PatchOrReplacement p -> Maybe (PatchTarget p)
38+
completePatchOrReplacement = \case
39+
PatchOrReplacement_Replacement t -> Just t
40+
PatchOrReplacement_Patch _ -> Nothing
41+
42+
-- | To apply a 'PatchOrReplacement p' apply the the underlying 'p' or
43+
-- substitute the replacement 'PatchTarget p'.
44+
instance Patch p => Patch (PatchOrReplacement p) where
45+
type PatchTarget (PatchOrReplacement p) = PatchTarget p
46+
apply = \case
47+
PatchOrReplacement_Patch p -> apply p
48+
PatchOrReplacement_Replacement v -> \_ -> Just v
49+
50+
instance ( Monoid p
51+
#if !MIN_VERSION_base(4,11,0)
52+
, Semigroup p
53+
#endif
54+
, Patch p
55+
) => Monoid (PatchOrReplacement p) where
56+
mempty = PatchOrReplacement_Patch mempty
57+
mappend = (<>)
58+
59+
instance (Semigroup p, Patch p) => Semigroup (PatchOrReplacement p) where
60+
(<>) = curry $ \case
61+
(PatchOrReplacement_Patch a, PatchOrReplacement_Patch b) -> PatchOrReplacement_Patch $ a <> b
62+
(PatchOrReplacement_Patch a, PatchOrReplacement_Replacement b) -> PatchOrReplacement_Replacement $ applyAlways a b
63+
(PatchOrReplacement_Replacement a, _) -> PatchOrReplacement_Replacement a

0 commit comments

Comments
 (0)