2{-# LANGUAGE ScopedTypeVariables #-}
3{-# LANGUAGE TypeFamilies #-}
4-- | The interface for types which represent changes made to other types
5module Data.Patch.Class where
7import Data.Functor.Identity
10#if !MIN_VERSION_base(4,11,0)
11import Data.Semigroup (Semigroup(..))
15-- | A 'Patch' type represents a kind of change made to a datastructure.
17-- If an instance of 'Patch' is also an instance of 'Semigroup', it should obey
18-- the law that @applyAlways (f <> g) == applyAlways f . applyAlways g@.
20 type PatchTarget p :: Type
21 -- | Apply the patch @p a@ to the value @a@. If no change is needed, return
23 apply :: p -> PatchTarget p -> Maybe (PatchTarget p)
25-- | Apply a 'Patch'; if it does nothing, return the original value
26applyAlways :: Patch p => p -> PatchTarget p -> PatchTarget p
27applyAlways p t = fromMaybe t $ apply p t
29-- | 'Identity' can be used as a 'Patch' that always fully replaces the value
30instance Patch (Identity a) where
31 type PatchTarget (Identity a) = a
32 apply (Identity a) _ = Just a
34-- | 'Proxy' can be used as a 'Patch' that does nothing.
35instance forall (a :: Type). Patch (Proxy a) where
36 type PatchTarget (Proxy a) = a
37 apply ~Proxy _ = Nothing
39-- | Like '(.)', but composes functions that return patches rather than
40-- functions that return new values. The Semigroup instance for patches must
41-- apply patches right-to-left, like '(.)'.
42composePatchFunctions :: (Patch p, Semigroup p) => (PatchTarget p -> p) -> (PatchTarget p -> p) -> PatchTarget p -> p
43composePatchFunctions g f a =
45 in g (applyAlways fp a) <> fp
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list