-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Type safe data migrations -- -- Please see the README on GitHub at -- https://github.com/agentultra/DataMigration#readme @package DataVersion @version 0.1.0.0 module Data.Migration.Internal type family RepToTree (a :: Type -> Type) :: [(Symbol, Type)] type family (++) (xs :: [k]) (ys :: [k]) :: [k] type family Sort (xs :: [(Symbol, k)]) type family Insert (x :: (Symbol, k)) (xs :: [(Symbol, k)]) type family Insert' (b :: Ordering) (x :: (Symbol, k)) (y :: (Symbol, k)) (ys :: [(Symbol, k)]) data DiffResult NoChange :: Symbol -> Type -> DiffResult Addition :: Symbol -> Type -> DiffResult Change :: Symbol -> Type -> Type -> DiffResult type family FieldDiff (a :: [(Symbol, Type)]) (b :: [(Symbol, Type)]) :: [DiffResult] type family FieldDiffImpl (b :: Ordering) (x :: (Symbol, Type)) (y :: (Symbol, Type)) (xs :: [(Symbol, Type)]) (ys :: [(Symbol, Type)]) :: [DiffResult] copyField :: forall name t from to. (HasField' name to t, HasField' name from t) => from -> to -> to class GTransform (ts :: [DiffResult]) (src :: Type) (dst :: Type) where { type family Function ts src dst :: Type; } gTransform :: GTransform ts src dst => dst -> src -> Function ts src dst class GUndefinedFields (o :: * -> *) gUndefinedFields :: GUndefinedFields o => o x -- | Don't use this, it's not meant to be useful undefinedFields :: (Generic t, GUndefinedFields (Rep t)) => t instance (GHC.Generics.Generic dst, Data.Migration.Internal.GUndefinedFields (GHC.Generics.Rep dst)) => Data.Migration.Internal.GTransform '[] src dst instance Data.Migration.Internal.GUndefinedFields o => Data.Migration.Internal.GUndefinedFields (GHC.Generics.M1 _3 _4 o) instance (Data.Migration.Internal.GUndefinedFields o1, Data.Migration.Internal.GUndefinedFields o2) => Data.Migration.Internal.GUndefinedFields (o1 GHC.Generics.:*: o2) instance Data.Migration.Internal.GUndefinedFields (GHC.Generics.K1 _1 t) instance (Data.Migration.Internal.GTransform ts src dst, Data.Generics.Product.Fields.HasField' name src t, Data.Generics.Product.Fields.HasField' name dst t) => Data.Migration.Internal.GTransform ('Data.Migration.Internal.NoChange name t : ts) src dst instance (Data.Migration.Internal.GTransform ts src dst, Data.Generics.Product.Fields.HasField' name dst t) => Data.Migration.Internal.GTransform ('Data.Migration.Internal.Addition name t : ts) src dst instance (Data.Migration.Internal.GTransform ts src dst, Data.Generics.Product.Fields.HasField' name src ti, Data.Generics.Product.Fields.HasField' name dst to) => Data.Migration.Internal.GTransform ('Data.Migration.Internal.Change name ti to : ts) src dst -- | To begin migrating your data start with a type family for your record -- and index it with a natural number -- --
-- data family Foo (version :: Nat)
--
-- newtype MyString = MyString { unMyString :: String }
-- deriving (IsString, Show, Eq)
--
-- data instance Foo 0
-- = FooV0
-- { _fooId :: Int
-- , _fooName :: String
-- }
-- deriving (Generic, Show, Eq)
--
-- data instance Foo 1
-- = FooV1
-- { _fooId :: Int
-- , _fooName :: MyString
-- , _fooHonorific :: String
-- }
-- deriving (Generic, Show, Eq)
--
-- instance Transform Foo 0 where
-- up v = genericUp v (const "esquire") (const MyString)
-- down v = genericDown v (const unMyString)
--
--
-- You provide an instance of the Transform class for your type in order
-- to specify how to transform version n to version n + 1
-- and back.
--
-- Presently only simple record types are supported. More to come in the
-- future.
module Data.Migration
-- | Implement this class on your type family instance to migrate values of
-- your type to the new version and back
class Transform (f :: Nat -> Type) (n :: Nat)
up :: Transform f n => f n -> f (n + 1)
down :: Transform f n => f (n + 1) -> f n
-- | Using this function in your up transformation ensures that you
-- only have to provide functions for fields that change or are added.
genericUp :: forall n src diff. (diff ~ FieldDiff (Sort (RepToTree (Rep (src n)))) (Sort (RepToTree (Rep (src (n + 1))))), GTransform diff (src n) (src (n + 1)), Generic (src (n + 1)), GUndefinedFields (Rep (src (n + 1)))) => src n -> Function diff (src n) (src (n + 1))
-- | This is the opposite of genericUp.
genericDown :: forall n src diff. (diff ~ FieldDiff (Sort (RepToTree (Rep (src (n + 1))))) (Sort (RepToTree (Rep (src n)))), GTransform diff (src (n + 1)) (src n), Generic (src n), GUndefinedFields (Rep (src n))) => src (n + 1) -> Function diff (src (n + 1)) (src n)