{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE InstanceSigs #-}
module Drasil.Database.Chunk
  ( Chunk,
    IsChunk,
    HasChunkRefs (..),
    mkChunk,
    unChunk,
    chunkType,
  )
where
import Control.Lens ((^.), to, Getter)
import Data.Typeable (Proxy (Proxy), TypeRep, Typeable, cast, typeOf, typeRep)
import qualified Data.Set as S
import Drasil.Database.UID (HasUID (..), UID)
class HasChunkRefs a where
  chunkRefs :: a -> S.Set UID
type IsChunk a = (HasUID a, HasChunkRefs a, Typeable a)
data Chunk = forall a. IsChunk a => Chunk a
instance Eq Chunk where
  (==) :: Chunk -> Chunk -> Bool
  Chunk
l == :: Chunk -> Chunk -> Bool
== Chunk
r = Chunk
l Chunk -> Getting UID Chunk UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID Chunk UID
forall c. HasUID c => Getter c UID
Getter Chunk UID
uid UID -> UID -> Bool
forall a. Eq a => a -> a -> Bool
== Chunk
r Chunk -> Getting UID Chunk UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID Chunk UID
forall c. HasUID c => Getter c UID
Getter Chunk UID
uid
instance HasUID Chunk where
  uid :: Getter Chunk UID
  uid :: Getter Chunk UID
uid = (Chunk -> UID) -> (UID -> f UID) -> Chunk -> f Chunk
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to (\(Chunk a
c) -> a
c a -> Getting UID a UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID a UID
forall c. HasUID c => Getter c UID
Getter a UID
uid)
mkChunk :: IsChunk a => a -> Chunk
mkChunk :: forall a. IsChunk a => a -> Chunk
mkChunk a
a
  | a -> TypeRep
forall a. Typeable a => a -> TypeRep
typeOf a
a TypeRep -> TypeRep -> Bool
forall a. Eq a => a -> a -> Bool
== Proxy Chunk -> TypeRep
forall {k} (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @Chunk) = [Char] -> Chunk
forall a. HasCallStack => [Char] -> a
error [Char]
"Cannot place a Chunk inside of a Chunk"
  | Bool
otherwise = a -> Chunk
forall a. IsChunk a => a -> Chunk
Chunk a
a
unChunk :: Typeable a => Chunk -> Maybe a
unChunk :: forall a. Typeable a => Chunk -> Maybe a
unChunk (Chunk a
c) = a -> Maybe a
forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
c
chunkType :: Chunk -> TypeRep
chunkType :: Chunk -> TypeRep
chunkType (Chunk a
c) = a -> TypeRep
forall a. Typeable a => a -> TypeRep
typeOf a
c