{-# LANGUAGE UndecidableInstances #-} -- | A binary version 0/1 field with seperate content for each version. module Data.ByteString.IsoBaseFileFormat.Boxes.Versioned (Versioned(..), ApplyVersioned(..), SelectByVersion) where import Data.ByteString.IsoBaseFileFormat.Boxes.Box import Data.Default import Data.Kind import Data.Singletons -- | Two alternative representations based on a /version/ index. -- Use this for box content that can be either 32 or 64 bit. data Versioned v0 v1 (version :: Nat) where V0 :: IsBoxContent v0 => v0 -> Versioned v0 v1 0 V1 :: IsBoxContent v1 => v1 -> Versioned v0 v1 1 instance (version ~ 0,IsBoxContent v0,Default v0) => Default (Versioned v0 v1 (version :: Nat)) where def = V0 def instance IsBoxContent (Versioned v0 v1 version) where boxSize (V0 c) = boxSize c boxSize (V1 c) = boxSize c boxBuilder (V0 c) = boxBuilder c boxBuilder (V1 c) = boxBuilder c data VersionedBox c where BoxV0 :: forall (v :: Nat -> Type). IsBoxContent (v 0) => v 0 -> VersionedBox v BoxV1 :: forall (v :: Nat -> Type). IsBoxContent (v 1) => v 1 -> VersionedBox v instance (IsBoxContent (b 0), Default (b 0)) => Default (VersionedBox b) where def = BoxV0 def instance IsBoxContent (VersionedBox c) where boxSize (BoxV0 c) = boxSize c boxSize (BoxV1 c) = boxSize c boxBuilder (BoxV0 c) = boxBuilder c boxBuilder (BoxV1 c) = boxBuilder c -- * Versions based on type level arrows -- | Two alternative representations based on a /version/ index. -- Use this for box content that can be either 32 or 64 bit. data ApplyVersioned (v' :: Nat ~> Type) where OnV0 :: forall (v :: Nat ~> Type). IsBoxContent (v @@ 0) => v @@ 0 -> ApplyVersioned v OnV1 :: forall (v :: Nat ~> Type). IsBoxContent (v @@ 1) => v @@ 1 -> ApplyVersioned v instance (IsBoxContent (b @@ 0), Default (b @@ 0)) => Default (ApplyVersioned b) where def = OnV0 def instance IsBoxContent (ApplyVersioned c) where boxSize (OnV0 c) = boxSize c boxSize (OnV1 c) = boxSize c boxBuilder (OnV0 c) = boxBuilder c boxBuilder (OnV1 c) = boxBuilder c -- | A type level arrow that applys the type constructor to one of the two -- versions depending on the /version/ parameter. data SelectByVersion :: (a -> Type) -> a -> a -> Nat ~> Type type instance Apply (SelectByVersion f v0 v1) 0 = f v0 type instance Apply (SelectByVersion f v0 v1) 1 = f v1