bytepatch-0.3.0: src/StreamPatch/Patch.hs
-- | Core patch type definitions: patches, seeks, metadata.
module StreamPatch.Patch where
import Data.Kind
import GHC.Generics ( Generic )
import GHC.Natural
import Data.Vinyl
import Control.Applicative ( liftA2 )
type PatchLike = SeekKind -> [Type -> Type] -> Type -> Type
type Patch :: PatchLike
data Patch s fs a = Patch
{ patchData :: a
, patchSeek :: SeekRep s
, patchMeta :: FunctorRec fs a
} deriving (Generic)
deriving instance (Eq a, Eq (SeekRep s), Eq (Rec (Flap a) fs)) => Eq (Patch s fs a)
deriving instance (Show a, Show (SeekRep s), ReifyConstraint Show (Flap a) fs, RMap fs, RecordToList fs) => Show (Patch s fs a)
deriving instance (Functor (FunctorRec fs)) => Functor (Patch s fs)
-- Taken from vinyl-plus. Functor and Applicative instances were provided.
newtype Flap a f = Flap { getFlap :: f a } deriving (Eq, Show, Generic)
newtype FunctorRec fs a = FunctorRec { getFunctorRec :: Rec (Flap a) fs } deriving (Generic)
deriving instance (ReifyConstraint Show (Flap a) fs, RMap fs, RecordToList fs) => Show (FunctorRec fs a)
deriving instance Eq (Rec (Flap a) fs) => Eq (FunctorRec fs a)
instance Functor (FunctorRec '[]) where
fmap _ (FunctorRec RNil) = FunctorRec RNil
instance (Functor r, Functor (FunctorRec rs)) => Functor (FunctorRec (r ': rs)) where
fmap f (FunctorRec (Flap r :& rs)) =
FunctorRec (Flap (fmap f r) :& getFunctorRec (fmap f (FunctorRec rs)))
instance Applicative (FunctorRec '[]) where
pure _ = FunctorRec RNil
FunctorRec RNil <*> FunctorRec RNil = FunctorRec RNil
instance (Applicative r, Applicative (FunctorRec rs)) => Applicative (FunctorRec (r ': rs)) where
pure a = FunctorRec (Flap (pure a) :& getFunctorRec (pure a))
FunctorRec (Flap f :& fs) <*> FunctorRec (Flap a :& as) =
FunctorRec (Flap (f <*> a) :& getFunctorRec (FunctorRec fs <*> FunctorRec as))
instance Foldable (FunctorRec '[]) where
foldr _ z (FunctorRec RNil) = z
instance (Foldable r, Foldable (FunctorRec rs)) => Foldable (FunctorRec (r ': rs)) where
-- TODO foldr is harder lol
foldMap f (FunctorRec (Flap r :& rs)) = foldMap f r <> foldMap f (FunctorRec rs)
-- I am shit at this LOL
instance Traversable (FunctorRec '[]) where
traverse _ (FunctorRec RNil) = pure (FunctorRec RNil)
instance (Traversable r, Traversable (FunctorRec rs)) => Traversable (FunctorRec (r ': rs)) where
traverse
:: forall f a b. Applicative f
=> (a -> f b)
-> (FunctorRec (r ': rs)) a
-> f (FunctorRec (r ': rs) b)
traverse f (FunctorRec (Flap (r :: r a) :& rs)) =
FunctorRec <$> rBoth
where
rBoth :: f (Rec (Flap b) (r ': rs))
rBoth = liftA2 (:&) rHead rTail
rHead :: f (Flap b r)
rHead = Flap <$> traverse f r
rTail :: f (Rec (Flap b) rs)
rTail = getFunctorRec <$> traverse f (FunctorRec rs)
-- | What a patch seek value means.
data SeekKind
= FwdSeek -- ^ seeks only move cursor forward
| RelSeek -- ^ seeks are relative e.g. to a universal base, or a stream cursor
| AbsSeek -- ^ seeks specify an exact offset in stream
deriving (Eq, Show, Generic)
-- | Get the representation for a 'SeekKind'. Allows us a bit more safety.
type family SeekRep (s :: SeekKind) where
SeekRep 'FwdSeek = Natural
SeekRep 'RelSeek = Integer
SeekRep 'AbsSeek = Natural