large-records-0.1.0.0: src/Data/Record/Generic/Rep/Internal.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RoleAnnotations #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
-- | Definition of 'Rep' and functions that do not depend on ".Generic"
--
-- Defined as a separate module to avoid circular module dependencies.
module Data.Record.Generic.Rep.Internal (
Rep(..)
-- * Basic functions
, map'
, sequenceA
-- * Conversion
, unsafeFromList
, collapse
-- * Utility (for use in @.Rep@)
, compileToHere
) where
import Prelude hiding (sequenceA)
import qualified Prelude
import Data.Coerce (coerce)
import Data.SOP.BasicFunctors
import Data.Vector (Vector)
import GHC.Exts (Any)
import Language.Haskell.TH
import qualified Data.Vector as V
{-------------------------------------------------------------------------------
Representation
-------------------------------------------------------------------------------}
-- | Representation of some record @a@
--
-- The @f@ parameter describes which functor has been applied to all fields of
-- the record; in other words @Rep I@ is isomorphic to the record itself.
newtype Rep f a = Rep (Vector (f Any))
type role Rep representational nominal
{-------------------------------------------------------------------------------
Basic functions
-------------------------------------------------------------------------------}
-- | Strict map
--
-- @map' f x@ is strict in @x@: if @x@ is undefined, @map f x@ will also be
-- undefined, even if @f@ never needs any values from @x@.
map' :: (forall x. f x -> g x) -> Rep f a -> Rep g a
map' f (Rep v) = Rep $ f <$> v
sequenceA :: Applicative m => Rep (m :.: f) a -> m (Rep f a)
sequenceA (Rep v) = Rep <$> Prelude.sequenceA (fmap unComp v)
{-------------------------------------------------------------------------------
Conversion
-------------------------------------------------------------------------------}
collapse :: Rep (K a) b -> [a]
collapse (Rep v) = coerce (V.toList v)
-- | Convert list to 'Rep'
--
-- Does not check that the length has the right number of elements.
unsafeFromList :: [b] -> Rep (K b) a
unsafeFromList = Rep . V.fromList . Prelude.map K
{-------------------------------------------------------------------------------
Some specialised instances for 'Rep
-------------------------------------------------------------------------------}
instance Show x => Show (Rep (K x) a) where
show (Rep v) =
show $ Prelude.map unK (V.toList v)
instance Eq x => Eq (Rep (K x) a) where
Rep v == Rep v' =
Prelude.map unK (V.toList v)
== Prelude.map unK (V.toList v')
{-------------------------------------------------------------------------------
Internal utility
-------------------------------------------------------------------------------}
compileToHere :: Q [Dec]
compileToHere = return []