{-# LANGUAGE CPP #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
module Data.Patch.Class where
import Data.Functor.Identity
import Data.Kind (Type)
import Data.Maybe
import Data.Semigroup
( Sum (..)
, Product (..)
#if !MIN_VERSION_base(4,11,0)
, Semigroup(..)
#endif
)
import Data.Proxy
class Patch p where
type PatchTarget p :: Type
apply :: p -> PatchTarget p -> Maybe (PatchTarget p)
applyAlways :: Patch p => p -> PatchTarget p -> PatchTarget p
applyAlways :: forall p. Patch p => p -> PatchTarget p -> PatchTarget p
applyAlways p
p PatchTarget p
t = PatchTarget p -> Maybe (PatchTarget p) -> PatchTarget p
forall a. a -> Maybe a -> a
fromMaybe PatchTarget p
t (Maybe (PatchTarget p) -> PatchTarget p)
-> Maybe (PatchTarget p) -> PatchTarget p
forall a b. (a -> b) -> a -> b
$ p -> PatchTarget p -> Maybe (PatchTarget p)
forall p. Patch p => p -> PatchTarget p -> Maybe (PatchTarget p)
apply p
p PatchTarget p
t
instance Patch (Identity a) where
type PatchTarget (Identity a) = a
apply :: Identity a
-> PatchTarget (Identity a) -> Maybe (PatchTarget (Identity a))
apply (Identity a
a) PatchTarget (Identity a)
_ = a -> Maybe a
forall a. a -> Maybe a
Just a
a
instance forall (a :: Type). Patch (Proxy a) where
type PatchTarget (Proxy a) = a
apply :: Proxy a -> PatchTarget (Proxy a) -> Maybe (PatchTarget (Proxy a))
apply ~Proxy a
Proxy PatchTarget (Proxy a)
_ = Maybe a
Maybe (PatchTarget (Proxy a))
forall a. Maybe a
Nothing
instance (Num a, Eq a) => Patch (Sum a) where
type PatchTarget (Sum a) = a
apply :: Sum a -> PatchTarget (Sum a) -> Maybe (PatchTarget (Sum a))
apply (Sum a
a) PatchTarget (Sum a)
b = if a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 then Maybe a
Maybe (PatchTarget (Sum a))
forall a. Maybe a
Nothing else PatchTarget (Sum a) -> Maybe (PatchTarget (Sum a))
forall a. a -> Maybe a
Just (PatchTarget (Sum a) -> Maybe (PatchTarget (Sum a)))
-> PatchTarget (Sum a) -> Maybe (PatchTarget (Sum a))
forall a b. (a -> b) -> a -> b
$ a
a a -> a -> a
forall a. Num a => a -> a -> a
+ a
PatchTarget (Sum a)
b
instance (Num a, Eq a) => Patch (Product a) where
type PatchTarget (Product a) = a
apply :: Product a
-> PatchTarget (Product a) -> Maybe (PatchTarget (Product a))
apply (Product a
a) PatchTarget (Product a)
b = if a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
1 then Maybe a
Maybe (PatchTarget (Product a))
forall a. Maybe a
Nothing else PatchTarget (Product a) -> Maybe (PatchTarget (Product a))
forall a. a -> Maybe a
Just (PatchTarget (Product a) -> Maybe (PatchTarget (Product a)))
-> PatchTarget (Product a) -> Maybe (PatchTarget (Product a))
forall a b. (a -> b) -> a -> b
$ a
a a -> a -> a
forall a. Num a => a -> a -> a
* a
PatchTarget (Product a)
b
composePatchFunctions :: (Patch p, Semigroup p) => (PatchTarget p -> p) -> (PatchTarget p -> p) -> PatchTarget p -> p
composePatchFunctions :: forall p.
(Patch p, Semigroup p) =>
(PatchTarget p -> p) -> (PatchTarget p -> p) -> PatchTarget p -> p
composePatchFunctions PatchTarget p -> p
g PatchTarget p -> p
f PatchTarget p
a =
let fp :: p
fp = PatchTarget p -> p
f PatchTarget p
a
in PatchTarget p -> p
g (p -> PatchTarget p -> PatchTarget p
forall p. Patch p => p -> PatchTarget p -> PatchTarget p
applyAlways p
fp PatchTarget p
a) p -> p -> p
forall a. Semigroup a => a -> a -> a
<> p
fp