Skip to content

Commit 6ef716a

Browse files
committed
Merge branch 'patch-map-inner-patch-desugar' into dpatch-map-inner-patch
2 parents 584334f + 32a1f2f commit 6ef716a

16 files changed

+983
-378
lines changed

.github/workflows/haskell.yml

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
name: github-action
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
build:
7+
strategy:
8+
matrix:
9+
ghc: ['8.0.2', '8.2.2', '8.4.4', '8.6.5', '8.8.4', '8.10.2']
10+
os: ['ubuntu-latest', 'macos-latest']
11+
exclude:
12+
# There are some linker warnings in 802 on darwin that
13+
# cause compilation to fail
14+
# See https://github.com/NixOS/nixpkgs/issues/25139
15+
- ghc: '8.0.2'
16+
os: 'macos-latest'
17+
runs-on: ${{ matrix.os }}
18+
19+
name: GHC ${{ matrix.ghc }} on ${{ matrix.os }}
20+
steps:
21+
- uses: actions/checkout@v2
22+
- uses: actions/setup-haskell@v1
23+
with:
24+
ghc-version: ${{ matrix.ghc }}
25+
- name: Cache
26+
uses: actions/cache@v1
27+
env:
28+
cache-name: cache-cabal
29+
with:
30+
path: ~/.cabal
31+
key: ${{ runner.os }}-${{ matrix.ghc }}-build-${{ env.cache-name }}-${{ hashFiles('**/*.cabal') }}-${{ hashFiles('**/cabal.project') }}
32+
restore-keys: |
33+
${{ runner.os }}-${{ matrix.ghc }}-build-${{ env.cache-name }}-
34+
${{ runner.os }}-${{ matrix.ghc }}-build-
35+
${{ runner.os }}-${{ matrix.ghc }}-
36+
${{ runner.os }}
37+
38+
- name: Install dependencies
39+
run: |
40+
cabal update
41+
cabal build --only-dependencies --enable-tests --enable-benchmarks
42+
- name: Build
43+
run: cabal build --enable-tests --enable-benchmarks all
44+
- name: Run tests
45+
run: cabal test all
46+
- name: Build Docs
47+
run: cabal haddock

CONTRIBUTING.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Before opening an issue, please check whether your issue has already been report
1616
* Describe the issue you're encountering or the suggestion you're making
1717
* Include any relevant steps to reproduce or code samples you can. It's always easier for us to debug if we have something that demonstrates the error.
1818
* Let us know what version of patch you were using. If you're using a github checkout, provide the git hash.
19-
* Describe how you're building patch (i.e., via patch-platform, cabal install, stack, obelisk, etc.). If you're using patch-platform or obelisk, provide the git hash of your checkout.
19+
* Describe how you're building patch (i.e., via reflex-platform, cabal install, stack, obelisk, etc.). If you're using reflex-platform or obelisk, provide the git hash of your checkout.
2020

2121
## Submitting Changes
2222

ChangeLog.md

+24
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,30 @@
66

77
* `PatchDMapWithMove` supports moves with a patch.
88

9+
* Rewrite `PatchMapWithMove` in terms of `PatchMapWithPatchingMove`.
10+
Care is taken to make this not a breaking change.
11+
In particular, `PatchMapWithMove` is a newtype of `PatchMapWithPatchingMove`, as is the `NodeInfo` and `From` of `PatchMapWithPatchingMove`'s versions of those.
12+
There are complete constructor and field patterns too, and everything is
13+
exported under the newtype as real constructors and fields would be.
14+
15+
## 0.0.4.0
16+
17+
* Enable PolyKinds
18+
19+
## 0.0.3.2
20+
21+
* Update version bounds
22+
23+
## 0.0.3.1
24+
25+
* Replace `fromJust` with something easier to debug.
26+
27+
## 0.0.3.0
28+
29+
* Create `PatchMapWithPatchingMove` variant which supports moves with a patch.
30+
31+
* Create `DecidablyEmpty` subclass of `Monoid`.
32+
933
## 0.0.2.0
1034

1135
* Consistently provide:

README.md

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
## Patch
1+
# patch
22

3-
Infrastructure for writing patches which act on other types.
3+
[![Haskell](https://img.shields.io/badge/language-Haskell-orange.svg)](https://haskell.org) [![Hackage](https://img.shields.io/hackage/v/patch.svg)](https://hackage.haskell.org/package/patch) [![Hackage CI](https://matrix.hackage.haskell.org/api/v2/packages/patch/badge)](https://matrix.hackage.haskell.org/#/package/patch) [![Travis CI](https://api.travis-ci.org/reflex-frp/patch.svg?branch=develop)](https://travis-ci.org/reflex-frp/patch) [![BSD3 License](https://img.shields.io/badge/license-BSD3-blue.svg)](https://github.com/reflex-frp/patch/LICENSE)
44

5-
A `Patch` type represents a kind of change made to a datastructure.
5+
Data structures for describing changes to other data structures.
6+
7+
A `Patch` type represents a kind of change made to a data structure.
68

79
```haskell
810
class Patch p where
@@ -12,7 +14,7 @@ class Patch p where
1214
apply :: p -> PatchTarget p -> Maybe (PatchTarget p)
1315
```
1416

15-
### Patching Maps
17+
## Patching Maps
1618
For example, `Data.Patch.Map` defines the `PatchMap` type which can be used to patch `Map`s. A `PatchMap` represents updates to a `Map` that can insert, remove, or replace items in the `Map`. In this example, the `Map` is the `PatchTarget` and the `PatchMap` is the `Patch`. Keep in mind that there are many other possible `Patch`es that can be applied to a `Map` (i.e., `Map` can be the `PatchTarget` for many different `Patch` instances).
1719

1820
`PatchMap` is defined as:

patch.cabal

+16-10
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
Name: patch
2-
Version: 0.0.2.0
3-
Synopsis: Infrastructure for writing patches which act on other types.
2+
Version: 0.0.4.0
3+
Synopsis: Data structures for describing changes to other data structures.
44
Description:
5+
Data structures for describing changes to other data structures.
6+
.
57
In this library, a patch is something which can be applied, analogous to a
68
function, and which distinguishes returning the argument it was provided from
79
returning something else.
@@ -12,15 +14,15 @@ Maintainer: maintainer@obsidian.systems
1214
Stability: Experimental
1315
Category: FRP
1416
Build-type: Simple
15-
Cabal-version: >=1.9.2
17+
Cabal-version: >=1.10
1618
homepage: https://obsidian.systems
1719
bug-reports: https://github.com/reflex-frp/patch/issues
1820
extra-source-files:
1921
README.md
2022
ChangeLog.md
2123

2224
tested-with:
23-
GHC ==8.0.2 || ==8.2.2 || ==8.4.4 || ==8.6.5 || ==8.8.1
25+
GHC ==8.0.2 || ==8.2.2 || ==8.4.4 || ==8.6.5 || ==8.8.1
2426
GHCJS ==8.4
2527

2628
flag split-these
@@ -30,15 +32,16 @@ flag split-these
3032

3133
library
3234
hs-source-dirs: src
33-
build-depends: base >= 4.9 && < 4.14
35+
default-language: Haskell2010
36+
build-depends: base >= 4.9 && < 4.15
3437
, constraints-extras >= 0.3 && < 0.4
3538
, containers >= 0.6 && < 0.7
36-
, dependent-map >= 0.3 && < 0.4
37-
, dependent-sum >= 0.6 && < 0.7
39+
, dependent-map >= 0.3 && < 0.5
40+
, dependent-sum >= 0.6 && < 0.8
3841
, lens >= 4.7 && < 5
3942
, semigroupoids >= 4.0 && < 6
4043
, transformers >= 0.5.6.0 && < 0.6
41-
, witherable >= 0.3 && < 0.3.2
44+
, witherable >= 0.3 && < 0.4
4245

4346
exposed-modules: Control.Category.DecidablyEmpty
4447
, Data.Functor.Misc
@@ -51,11 +54,13 @@ library
5154
, Data.Patch.IntMap
5255
, Data.Patch.Map
5356
, Data.Patch.MapWithMove
57+
, Data.Patch.MapWithPatchingMove
5458

5559
ghc-options: -Wall -fwarn-redundant-constraints -fwarn-tabs
60+
default-extensions: PolyKinds
5661

5762
if flag(split-these)
58-
build-depends: these >= 1 && <1.1
63+
build-depends: these >= 1 && <1.2
5964
, these-lens >= 1 && <1.1
6065
, semialign >=1 && <1.2
6166
, monoidal-containers >= 0.6 && < 0.7
@@ -64,14 +69,15 @@ library
6469
, monoidal-containers == 0.4.0.0
6570

6671
test-suite hlint
72+
default-language: Haskell2010
6773
type: exitcode-stdio-1.0
6874
main-is: hlint.hs
6975
hs-source-dirs: test
7076
build-depends: base
7177
, directory
7278
, filepath
7379
, filemanip
74-
, hlint < 2.1 || >= 2.2.2
80+
, hlint (< 2.1 || >= 2.2.2) && < 3.3
7581
if impl(ghcjs)
7682
buildable: False
7783

src/Data/Functor/Misc.hs

+2-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
{-# LANGUAGE GADTs #-}
77
{-# LANGUAGE LambdaCase #-}
88
{-# LANGUAGE MultiParamTypeClasses #-}
9-
{-# LANGUAGE PatternSynonyms #-}
109
{-# LANGUAGE PolyKinds #-}
1110
{-# LANGUAGE RankNTypes #-}
1211
{-# LANGUAGE ScopedTypeVariables #-}
@@ -52,7 +51,7 @@ import qualified Data.IntMap as IntMap
5251
import Data.Map (Map)
5352
import qualified Data.Map as Map
5453
import qualified Data.Semigroupoid as Cat
55-
import Data.Some (Some(Some))
54+
import Data.Some (Some, mkSome)
5655
import Data.These
5756
import Data.Type.Equality ((:~:)(Refl))
5857
import Data.Typeable hiding (Refl)
@@ -140,7 +139,7 @@ intMapWithFunctorToDMap = DMap.fromDistinctAscList . map (\(k, v) -> Const2 k :=
140139
-- | Convert a 'DMap' to a regular 'Map' by forgetting the types associated with
141140
-- the keys, using a function to remove the wrapping 'Functor'
142141
weakenDMapWith :: (forall a. v a -> v') -> DMap k v -> Map (Some k) v'
143-
weakenDMapWith f = Map.fromDistinctAscList . map (\(k :=> v) -> (Some k, f v)) . DMap.toAscList
142+
weakenDMapWith f = Map.fromDistinctAscList . map (\(k :=> v) -> (mkSome k, f v)) . DMap.toAscList
144143

145144
--------------------------------------------------------------------------------
146145
-- WrapArg

src/Data/Monoid/DecidablyEmpty.hs

+111-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,115 @@
1+
{-# LANGUAGE CPP #-}
2+
{-# LANGUAGE DefaultSignatures #-}
3+
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4+
{-# LANGUAGE StandaloneDeriving #-}
5+
{-# LANGUAGE TypeOperators #-}
6+
17
-- TODO upstream somwhere else?
28
module Data.Monoid.DecidablyEmpty where
39

10+
import Data.Functor.Identity
11+
import Data.Functor.Const
12+
import Data.Monoid
13+
import Data.Maybe (isNothing)
14+
#if MIN_VERSION_base(4,11,0)
15+
import Data.Ord
16+
#endif
17+
import Data.Proxy
18+
import Data.Semigroup hiding (First, Last)
19+
#if MIN_VERSION_base(4,12,0)
20+
import GHC.Generics
21+
#endif
22+
23+
import qualified Data.IntSet as IntSet
24+
import qualified Data.IntMap as IntMap
25+
import qualified Data.Map as Map
26+
import qualified Data.Sequence as Seq
27+
import qualified Data.Set as Set
28+
29+
import Data.GADT.Compare
30+
import qualified Data.Dependent.Map as DMap
31+
32+
-- | A 'DecidablyEmpty' is one where it can be computed whether or not an
33+
-- arbitrary value is 'mempty'.
34+
--
35+
-- By using this class rather than 'Eq', we avoid unnecessary constraining the
36+
-- contents of 'Functor's. This makes it possible to efficiently combine and/or
37+
-- nest patch maps with 'Eq'-lacking values (e.g. functions) at the leaves.
438
class Monoid a => DecidablyEmpty a where
5-
isNull :: a -> Bool
39+
isEmpty :: a -> Bool
40+
default isEmpty :: Eq a => a -> Bool
41+
isEmpty = (==) mempty
42+
43+
-- base
44+
45+
instance DecidablyEmpty Ordering
46+
instance DecidablyEmpty ()
47+
instance DecidablyEmpty Any
48+
instance DecidablyEmpty All
49+
-- instance DecidablyEmpty Lifetime
50+
-- instance DecidablyEmpty Event
51+
instance DecidablyEmpty [a] where
52+
isEmpty = null
53+
instance
54+
#if MIN_VERSION_base(4,11,0)
55+
Semigroup a
56+
#else
57+
Monoid a
58+
#endif
59+
=> DecidablyEmpty (Maybe a) where
60+
isEmpty = isNothing
61+
deriving instance (Num a, DecidablyEmpty a) => DecidablyEmpty (Product a)
62+
deriving instance (DecidablyEmpty a, Num a) => DecidablyEmpty (Sum a)
63+
deriving instance DecidablyEmpty a => DecidablyEmpty (Dual a)
64+
instance DecidablyEmpty (First a) where
65+
isEmpty (First a) = isNothing a
66+
instance DecidablyEmpty (Last a) where
67+
isEmpty (Last a) = isNothing a
68+
deriving instance DecidablyEmpty a => DecidablyEmpty (Identity a)
69+
instance Semigroup a => DecidablyEmpty (Option a) where
70+
isEmpty (Option a) = isNothing a
71+
deriving instance DecidablyEmpty m => DecidablyEmpty (WrappedMonoid m)
72+
instance (Ord a, Bounded a) => DecidablyEmpty (Max a)
73+
instance (Ord a, Bounded a) => DecidablyEmpty (Min a)
74+
instance DecidablyEmpty (Proxy s)
75+
deriving instance DecidablyEmpty a => DecidablyEmpty (Const a b)
76+
#if MIN_VERSION_base(4,11,0)
77+
deriving instance DecidablyEmpty a => DecidablyEmpty (Down a)
78+
#endif
79+
#if MIN_VERSION_base(4,12,0)
80+
deriving instance DecidablyEmpty p => DecidablyEmpty (Par1 p)
81+
instance DecidablyEmpty (U1 p)
82+
deriving instance DecidablyEmpty (f p) => DecidablyEmpty (Rec1 f p)
83+
deriving instance DecidablyEmpty (f p) => DecidablyEmpty (M1 i c f p)
84+
deriving instance DecidablyEmpty c => DecidablyEmpty (K1 i c p)
85+
instance (DecidablyEmpty (f p), DecidablyEmpty (g p)) => DecidablyEmpty ((f :*: g) p) where
86+
isEmpty (x :*: y) = isEmpty x && isEmpty y
87+
deriving instance DecidablyEmpty (f (g p)) => DecidablyEmpty ((f :.: g) p)
88+
#endif
89+
90+
instance (DecidablyEmpty a, DecidablyEmpty b) => DecidablyEmpty (a, b) where
91+
isEmpty (a, b) = isEmpty a && isEmpty b
92+
instance (DecidablyEmpty a, DecidablyEmpty b, DecidablyEmpty c) => DecidablyEmpty (a, b, c) where
93+
isEmpty (a, b, c) = isEmpty a && isEmpty b && isEmpty c
94+
instance (DecidablyEmpty a, DecidablyEmpty b, DecidablyEmpty c, DecidablyEmpty d) => DecidablyEmpty (a, b, c, d) where
95+
isEmpty (a, b, c, d) = isEmpty a && isEmpty b && isEmpty c && isEmpty d
96+
instance (DecidablyEmpty a, DecidablyEmpty b, DecidablyEmpty c, DecidablyEmpty d, DecidablyEmpty e) => DecidablyEmpty (a, b, c, d, e) where
97+
isEmpty (a, b, c, d, e) = isEmpty a && isEmpty b && isEmpty c && isEmpty d && isEmpty e
98+
99+
-- containers
100+
101+
instance DecidablyEmpty IntSet.IntSet where
102+
isEmpty = IntSet.null
103+
instance DecidablyEmpty (IntMap.IntMap v) where
104+
isEmpty = IntMap.null
105+
instance Ord k => DecidablyEmpty (Map.Map k v) where
106+
isEmpty = Map.null
107+
instance DecidablyEmpty (Seq.Seq v) where
108+
isEmpty = Seq.null
109+
instance Ord k => DecidablyEmpty (Set.Set k) where
110+
isEmpty = Set.null
111+
112+
-- dependent-map
113+
114+
instance GCompare k => DecidablyEmpty (DMap.DMap k v) where
115+
isEmpty = DMap.null

src/Data/Patch.hs

+3-3
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,16 @@ import Data.Functor.Const (Const (..))
1818
import Data.Functor.Identity
1919
import Data.Map.Monoidal (MonoidalMap)
2020
import Data.Proxy
21-
#if !MIN_VERSION_base(4,9,0)
22-
import Data.Semigroup (Semigroup (..), (<>))
21+
#if !MIN_VERSION_base(4,11,0)
22+
import Data.Semigroup (Semigroup (..))
2323
#endif
2424
import GHC.Generics
2525

2626
import Data.Patch.Class as X
2727
import Data.Patch.DMap as X hiding (getDeletions)
2828
import Data.Patch.DMapWithMove as X
2929
( PatchDMapWithMove, const2PatchDMapWithMoveWith, mapPatchDMapWithMove
30-
, patchDMapWithMoveToPatchMapWithMoveWith
30+
, patchDMapWithMoveToPatchMapWithPatchingMoveWith
3131
, traversePatchDMapWithMoveWithKey, unPatchDMapWithMove
3232
, unsafePatchDMapWithMove, weakenPatchDMapWithMoveWith
3333
)

0 commit comments

Comments
 (0)