Skip to content

Commit da266c5

Browse files
authored
Merge pull request #12 from reflex-frp/add-WithIndex-instances
Add *WithIndex instances
2 parents eb6b6e5 + c6216d3 commit da266c5

File tree

8 files changed

+114
-48
lines changed

8 files changed

+114
-48
lines changed

ChangeLog.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
# Revision history for patch
22

3+
## Unreleased
4+
5+
* Consistently provide:
6+
7+
- `Wrapped` instances
8+
9+
- `*WithIndex` instances
10+
11+
- `un*` newtype unwrappers
12+
13+
for `PatchMap`, `PatchIntMap`, and `PatchMapWithMove`.
14+
315
## 0.0.1.0
416

517
* Support older GHCs with `split-these` flag.

dep/reflex-platform/default.nix

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# DO NOT HAND-EDIT THIS FILE
2-
import ((import <nixpkgs> {}).fetchFromGitHub (
3-
let json = builtins.fromJSON (builtins.readFile ./github.json);
4-
in { inherit (json) owner repo rev sha256;
5-
private = json.private or false;
6-
}
7-
))
2+
let fetch = { private ? false, fetchSubmodules ? false, owner, repo, rev, sha256, ... }:
3+
if !fetchSubmodules && !private then builtins.fetchTarball {
4+
url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; inherit sha256;
5+
} else (import <nixpkgs> {}).fetchFromGitHub {
6+
inherit owner repo rev sha256 fetchSubmodules private;
7+
};
8+
in import (fetch (builtins.fromJSON (builtins.readFile ./github.json)))

dep/reflex-platform/github.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"owner": "reflex-frp",
33
"repo": "reflex-platform",
44
"branch": "master",
5-
"rev": "510b990d0b11f0626afbec5fe8575b5b2395391b",
6-
"sha256": "09cmahsbxr0963wq171c7j139iyzz49hramr4v9nsf684wcwkngv"
5+
"private": false,
6+
"rev": "c9d11db1b98855fe8ab24a3ff6a5dbe0ad902ad9",
7+
"sha256": "0sfzkqdvyah5mwvmli0wq1nl0b8cvk2cmfgfy4rz57wv42x3099y"
78
}

patch.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ library
3535
, containers >= 0.6 && < 0.7
3636
, dependent-map >= 0.3 && < 0.4
3737
, dependent-sum >= 0.6 && < 0.7
38+
, lens >= 4.7 && < 5
3839
, semigroupoids >= 4.0 && < 6
3940
, transformers >= 0.5.6.0 && < 0.6
4041
, witherable >= 0.3 && < 0.3.2

release.nix

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,26 @@ let
1818
"ghcIosAarch64"
1919
];
2020
compilerPkgs = lib.genAttrs compilers (ghc: let
21-
src = builtins.filterSource (path: type: !(builtins.elem (baseNameOf path) [
22-
"release.nix"
23-
".git"
24-
"dist"
25-
"dist-newstyle"
26-
"cabal.haskell-ci"
27-
"cabal.project"
28-
".travis.yml"
29-
])) ./.;
30-
in reflex-platform.${ghc}.callCabal2nix "patch" src {});
21+
reflex-platform = reflex-platform-fun {
22+
inherit system;
23+
haskellOverlays = [
24+
# Use this package's source for reflex
25+
(self: super: {
26+
_dep = super._dep // {
27+
patch = builtins.filterSource (path: type: !(builtins.elem (baseNameOf path) [
28+
"release.nix"
29+
".git"
30+
"dist"
31+
"dist-newstyle"
32+
"cabal.haskell-ci"
33+
"cabal.project"
34+
".travis.yml"
35+
])) ./.;
36+
};
37+
})
38+
];
39+
};
40+
in reflex-platform.${ghc}.patch);
3141
in compilerPkgs // {
3242
cache = reflex-platform.pinBuildInputs "patch-${system}"
3343
(builtins.attrValues compilerPkgs);

src/Data/Patch/IntMap.hs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
1-
{-# LANGUAGE DeriveFoldable #-}
2-
{-# LANGUAGE DeriveFunctor #-}
31
{-# LANGUAGE DeriveTraversable #-}
2+
{-# LANGUAGE FlexibleInstances #-}
43
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4+
{-# LANGUAGE MultiParamTypeClasses #-}
5+
{-# LANGUAGE TemplateHaskell #-}
56
{-# LANGUAGE TypeFamilies #-}
7+
68
-- | Module containing 'PatchIntMap', a 'Patch' for 'IntMap' which allows for
79
-- insert/update or delete of associations.
810
module Data.Patch.IntMap where
911

12+
import Control.Lens
1013
import Data.IntMap.Strict (IntMap)
1114
import qualified Data.IntMap.Strict as IntMap
1215
import Data.Maybe
@@ -16,7 +19,20 @@ import Data.Patch.Class
1619
-- | 'Patch' for 'IntMap' which represents insertion or deletion of keys in the mapping.
1720
-- Internally represented by 'IntMap (Maybe a)', where @Just@ means insert/update
1821
-- and @Nothing@ means delete.
19-
newtype PatchIntMap a = PatchIntMap (IntMap (Maybe a)) deriving (Functor, Foldable, Traversable, Monoid)
22+
newtype PatchIntMap a = PatchIntMap { unPatchIntMap :: IntMap (Maybe a) }
23+
deriving ( Show, Read, Eq, Ord
24+
, Functor, Foldable, Traversable, Monoid
25+
)
26+
27+
-- | @a <> b@ will apply the changes of @b@ and then apply the changes of @a@.
28+
-- If the same key is modified by both patches, the one on the left will take
29+
-- precedence.
30+
instance Semigroup (PatchIntMap v) where
31+
PatchIntMap a <> PatchIntMap b = PatchIntMap $ a `mappend` b --TODO: Add a semigroup instance for Map
32+
-- PatchMap is idempotent, so stimes n is id for every n
33+
stimes = stimesIdempotentMonoid
34+
35+
makeWrapped ''PatchIntMap
2036

2137
-- | Apply the insertions or deletions to a given 'IntMap'.
2238
instance Patch (PatchIntMap a) where
@@ -26,13 +42,10 @@ instance Patch (PatchIntMap a) where
2642
adds = IntMap.mapMaybe id p
2743
in IntMap.union adds $ v `IntMap.difference` removes
2844

29-
-- | @a <> b@ will apply the changes of @b@ and then apply the changes of @a@.
30-
-- If the same key is modified by both patches, the one on the left will take
31-
-- precedence.
32-
instance Semigroup (PatchIntMap v) where
33-
PatchIntMap a <> PatchIntMap b = PatchIntMap $ a `mappend` b --TODO: Add a semigroup instance for Map
34-
-- PatchMap is idempotent, so stimes n is id for every n
35-
stimes = stimesIdempotentMonoid
45+
instance FunctorWithIndex Int PatchIntMap
46+
instance FoldableWithIndex Int PatchIntMap
47+
instance TraversableWithIndex Int PatchIntMap where
48+
itraversed = _Wrapped . itraversed . traversed
3649

3750
-- | Map a function @Int -> a -> b@ over all @a@s in the given @'PatchIntMap' a@
3851
-- (that is, all inserts/updates), producing a @PatchIntMap b@.

src/Data/Patch/Map.hs

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1+
{-# LANGUAGE DeriveTraversable #-}
2+
{-# LANGUAGE FlexibleInstances #-}
13
{-# LANGUAGE LambdaCase #-}
4+
{-# LANGUAGE MultiParamTypeClasses #-}
5+
{-# LANGUAGE StandaloneDeriving #-}
6+
{-# LANGUAGE TemplateHaskell #-}
27
{-# LANGUAGE TypeFamilies #-}
8+
39
-- | 'Patch'es on 'Map' that consist only of insertions (including overwrites)
410
-- and deletions
511
module Data.Patch.Map where
612

713
import Data.Patch.Class
814

15+
import Control.Lens
916
import Data.Map (Map)
1017
import qualified Data.Map as Map
1118
import Data.Maybe
@@ -15,7 +22,23 @@ import Data.Semigroup
1522
-- deleted. Insertions are represented as values wrapped in 'Just', while
1623
-- deletions are represented as 'Nothing's
1724
newtype PatchMap k v = PatchMap { unPatchMap :: Map k (Maybe v) }
18-
deriving (Show, Read, Eq, Ord)
25+
deriving ( Show, Read, Eq, Ord
26+
, Foldable, Traversable
27+
)
28+
29+
-- | 'fmap'ping a 'PatchMap' will alter all of the values it will insert.
30+
-- Deletions are unaffected.
31+
deriving instance Functor (PatchMap k)
32+
33+
-- | @a <> b@ will apply the changes of @b@ and then apply the changes of @a@.
34+
-- If the same key is modified by both patches, the one on the left will take
35+
-- precedence.
36+
instance Ord k => Semigroup (PatchMap k v) where
37+
PatchMap a <> PatchMap b = PatchMap $ a `mappend` b --TODO: Add a semigroup instance for Map
38+
-- PatchMap is idempotent, so stimes n is id for every n
39+
stimes = stimesIdempotentMonoid
40+
41+
makeWrapped ''PatchMap
1942

2043
-- | Apply the insertions or deletions to a given 'Map'.
2144
instance Ord k => Patch (PatchMap k v) where
@@ -28,24 +51,16 @@ instance Ord k => Patch (PatchMap k v) where
2851
Nothing -> Just ()
2952
Just _ -> Nothing
3053

31-
-- | @a <> b@ will apply the changes of @b@ and then apply the changes of @a@.
32-
-- If the same key is modified by both patches, the one on the left will take
33-
-- precedence.
34-
instance Ord k => Semigroup (PatchMap k v) where
35-
PatchMap a <> PatchMap b = PatchMap $ a `mappend` b --TODO: Add a semigroup instance for Map
36-
-- PatchMap is idempotent, so stimes n is id for every n
37-
stimes = stimesIdempotentMonoid
54+
instance FunctorWithIndex k (PatchMap k)
55+
instance FoldableWithIndex k (PatchMap k)
56+
instance TraversableWithIndex k (PatchMap k) where
57+
itraverse f (PatchMap x) = PatchMap <$> itraverse (traverse . f) x
3858

3959
-- | The empty 'PatchMap' contains no insertions or deletions
4060
instance Ord k => Monoid (PatchMap k v) where
4161
mempty = PatchMap mempty
4262
mappend = (<>)
4363

44-
-- | 'fmap'ping a 'PatchMap' will alter all of the values it will insert.
45-
-- Deletions are unaffected.
46-
instance Functor (PatchMap k) where
47-
fmap f = PatchMap . fmap (fmap f) . unPatchMap
48-
4964
-- | Returns all the new elements that will be added to the 'Map'
5065
patchMapNewElements :: PatchMap k v -> [v]
5166
patchMapNewElements (PatchMap p) = catMaybes $ Map.elems p

src/Data/Patch/MapWithMove.hs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
1-
{-# LANGUAGE DeriveFoldable #-}
2-
{-# LANGUAGE DeriveFunctor #-}
31
{-# LANGUAGE DeriveTraversable #-}
42
{-# LANGUAGE FlexibleContexts #-}
3+
{-# LANGUAGE FlexibleInstances #-}
54
{-# LANGUAGE LambdaCase #-}
5+
{-# LANGUAGE MultiParamTypeClasses #-}
66
{-# LANGUAGE PatternGuards #-}
77
{-# LANGUAGE ScopedTypeVariables #-}
8+
{-# LANGUAGE TemplateHaskell #-}
9+
{-# LANGUAGE TypeApplications #-}
810
{-# LANGUAGE TypeFamilies #-}
11+
912
-- | 'Patch'es on 'Map' that can insert, delete, and move values from one key to
1013
-- another
1114
module Data.Patch.MapWithMove where
1215

1316
import Data.Patch.Class
1417

1518
import Control.Arrow
19+
import Control.Lens hiding (from, to)
1620
import Control.Monad.Trans.State
1721
import Data.Foldable
1822
import Data.Function
@@ -28,7 +32,13 @@ import Data.Tuple
2832
-- | Patch a Map with additions, deletions, and moves. Invariant: If key @k1@
2933
-- is coming from @From_Move k2@, then key @k2@ should be going to @Just k1@,
3034
-- and vice versa. There should never be any unpaired From/To keys.
31-
newtype PatchMapWithMove k v = PatchMapWithMove (Map k (NodeInfo k v)) deriving (Show, Eq, Ord, Functor, Foldable, Traversable)
35+
newtype PatchMapWithMove k v = PatchMapWithMove
36+
{ -- | Extract the internal representation of the 'PatchMapWithMove'
37+
unPatchMapWithMove :: Map k (NodeInfo k v)
38+
}
39+
deriving ( Show, Read, Eq, Ord
40+
, Functor, Foldable, Traversable
41+
)
3242

3343
-- | Holds the information about each key: where its new value should come from,
3444
-- and where its old value should go to
@@ -53,6 +63,13 @@ data From k v
5363
-- that means it will be deleted.
5464
type To = Maybe
5565

66+
makeWrapped ''PatchMapWithMove
67+
68+
instance FunctorWithIndex k (PatchMapWithMove k)
69+
instance FoldableWithIndex k (PatchMapWithMove k)
70+
instance TraversableWithIndex k (PatchMapWithMove k) where
71+
itraverse f (PatchMapWithMove x) = PatchMapWithMove <$> itraverse (traverse . f) x
72+
5673
-- | Create a 'PatchMapWithMove', validating it
5774
patchMapWithMove :: Ord k => Map k (NodeInfo k v) -> Maybe (PatchMapWithMove k v)
5875
patchMapWithMove m = if valid then Just $ PatchMapWithMove m else Nothing
@@ -70,10 +87,6 @@ patchMapWithMoveInsertAll m = PatchMapWithMove $ flip fmap m $ \v -> NodeInfo
7087
, _nodeInfo_to = Nothing
7188
}
7289

73-
-- | Extract the internal representation of the 'PatchMapWithMove'
74-
unPatchMapWithMove :: PatchMapWithMove k v -> Map k (NodeInfo k v)
75-
unPatchMapWithMove (PatchMapWithMove p) = p
76-
7790
-- | Make a @'PatchMapWithMove' k v@ which has the effect of inserting or updating a value @v@ to the given key @k@, like 'Map.insert'.
7891
insertMapKey :: k -> v -> PatchMapWithMove k v
7992
insertMapKey k v = PatchMapWithMove . Map.singleton k $ NodeInfo (From_Insert v) Nothing

0 commit comments

Comments
 (0)