Copyright | (c) 2019 Commonwealth Scientific and Industrial Research Organisation |
---|---|
License | BSD3 |
Maintainer | jack.kelly@data61.csiro.au |
Stability | experimental |
Portability | Portable |
Safe Haskell | Safe |
Language | Haskell2010 |
The Semialign
typeclass lets us line up two structures of the same
type. It's then possible to take a simple diff by comparing the points
of overlap.
A note on type variables
The return type of the diffing functions is very general, because we
might want to (say) diff two [a]
into an
,
IntMap
a
or some other structure. This generality can
hurt type inference.Map
Int a
The type signatures for all functions have the patch type as their
first type variable. For diff
/ diffNoEq
/ diffWith
, this allows
setting the return type with a single type application.
Synopsis
- diff :: forall p f i a. (FoldableWithIndex i f, Semialign f, Eq a, AsEmpty p, At p, Index p ~ i, IxValue p ~ Maybe a) => f a -> f a -> p
- diffNoEq :: forall p f i a. (FoldableWithIndex i f, Semialign f, AsEmpty p, At p, Index p ~ i, IxValue p ~ Maybe a) => f a -> f a -> p
- diffWith :: forall p f i a b c. (FoldableWithIndex i f, Semialign f, AsEmpty p, At p, Index p ~ i, IxValue p ~ c) => (These a b -> Maybe c) -> f a -> f b -> p
- patch :: forall p m i a. (FoldableWithIndex i p, At m, Index m ~ i, IxValue m ~ a) => p (Maybe a) -> m -> m
- patchWith :: forall p m i a b. (FoldableWithIndex i p, At m, Index m ~ i, IxValue m ~ a) => (Maybe a -> b -> Maybe a) -> p b -> m -> m
Diffing
diff :: forall p f i a. (FoldableWithIndex i f, Semialign f, Eq a, AsEmpty p, At p, Index p ~ i, IxValue p ~ Maybe a) => f a -> f a -> p Source #
Diff two structures.
>>>
:{
let old = fromList [("Alice", 1), ("Bob", 2)] new = fromList [("Alice", 3), ("Carol", 4)] in diff old new :: Map String (Maybe Int) :} fromList [("Alice",Just 3),("Bob",Nothing),("Carol",Just 4)]
Since: 0.1.0.0
diffNoEq :: forall p f i a. (FoldableWithIndex i f, Semialign f, AsEmpty p, At p, Index p ~ i, IxValue p ~ Maybe a) => f a -> f a -> p Source #
Diff two structures without requiring an Eq
instance. Instead,
always assume a new value wherever the structures align:
>>>
:{
let old = fromList [("Alice", (+ 1))] new = fromList [("Alice", (* 2))] in ($ 3) <$> diffNoEq old new ! "Alice" :} Just 6
Since: 0.1.0.0
diffWith :: forall p f i a b c. (FoldableWithIndex i f, Semialign f, AsEmpty p, At p, Index p ~ i, IxValue p ~ c) => (These a b -> Maybe c) -> f a -> f b -> p Source #
Patching
patch :: forall p m i a. (FoldableWithIndex i p, At m, Index m ~ i, IxValue m ~ a) => p (Maybe a) -> m -> m Source #
Apply a patch to a structure.
>>>
patch (fromList [(0, Just 0), (1, Just 3), (2, Nothing)]) (fromList [(0, 1), (2, 3)])
fromList [(0,0),(1,3)]
When the types are compatible, patch
undoes diff
/ diffNoEq
:
\old new -> let p = diff @(Map Int (Maybe Int)) old (new :: Map Int Int) in (patch p old) == new
\old new -> let p = diffNoEq @(Map Int (Maybe Int)) old (new :: Map Int Int) in (patch p old) == new
Since: 0.1.0.0