{-# 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' :: (forall x. f x -> g x) -> Rep f a -> Rep g a
map' forall x. f x -> g x
f (Rep Vector (f Any)
v) = Vector (g Any) -> Rep g a
forall (f :: Type -> Type) a. Vector (f Any) -> Rep f a
Rep (Vector (g Any) -> Rep g a) -> Vector (g Any) -> Rep g a
forall a b. (a -> b) -> a -> b
$ f Any -> g Any
forall x. f x -> g x
f (f Any -> g Any) -> Vector (f Any) -> Vector (g Any)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Vector (f Any)
v

sequenceA :: Applicative m => Rep (m :.: f) a -> m (Rep f a)
sequenceA :: Rep (m :.: f) a -> m (Rep f a)
sequenceA (Rep Vector ((:.:) m f Any)
v) = Vector (f Any) -> Rep f a
forall (f :: Type -> Type) a. Vector (f Any) -> Rep f a
Rep (Vector (f Any) -> Rep f a) -> m (Vector (f Any)) -> m (Rep f a)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Vector (m (f Any)) -> m (Vector (f Any))
forall (t :: Type -> Type) (f :: Type -> Type) a.
(Traversable t, Applicative f) =>
t (f a) -> f (t a)
Prelude.sequenceA (((:.:) m f Any -> m (f Any))
-> Vector ((:.:) m f Any) -> Vector (m (f Any))
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap (:.:) m f Any -> m (f Any)
forall l k (f :: l -> Type) (g :: k -> l) (p :: k).
(:.:) f g p -> f (g p)
unComp Vector ((:.:) m f Any)
v)

{-------------------------------------------------------------------------------
  Conversion
-------------------------------------------------------------------------------}

collapse :: Rep (K a) b -> [a]
collapse :: Rep (K a) b -> [a]
collapse (Rep Vector (K a Any)
v) = [K a Any] -> [a]
coerce (Vector (K a Any) -> [K a Any]
forall a. Vector a -> [a]
V.toList Vector (K a Any)
v)

-- | Convert list to 'Rep'
--
-- Does not check that the length has the right number of elements.
unsafeFromList :: [b] -> Rep (K b) a
unsafeFromList :: [b] -> Rep (K b) a
unsafeFromList = Vector (K b Any) -> Rep (K b) a
forall (f :: Type -> Type) a. Vector (f Any) -> Rep f a
Rep (Vector (K b Any) -> Rep (K b) a)
-> ([b] -> Vector (K b Any)) -> [b] -> Rep (K b) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [K b Any] -> Vector (K b Any)
forall a. [a] -> Vector a
V.fromList ([K b Any] -> Vector (K b Any))
-> ([b] -> [K b Any]) -> [b] -> Vector (K b Any)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (b -> K b Any) -> [b] -> [K b Any]
forall a b. (a -> b) -> [a] -> [b]
Prelude.map b -> K b Any
forall k a (b :: k). a -> K a b
K

{-------------------------------------------------------------------------------
  Some specialised instances for 'Rep
-------------------------------------------------------------------------------}

instance Show x => Show (Rep (K x) a) where
  show :: Rep (K x) a -> String
show (Rep Vector (K x Any)
v) =
      [x] -> String
forall a. Show a => a -> String
show ([x] -> String) -> [x] -> String
forall a b. (a -> b) -> a -> b
$ (K x Any -> x) -> [K x Any] -> [x]
forall a b. (a -> b) -> [a] -> [b]
Prelude.map K x Any -> x
forall k a (b :: k). K a b -> a
unK (Vector (K x Any) -> [K x Any]
forall a. Vector a -> [a]
V.toList Vector (K x Any)
v)

instance Eq x => Eq (Rep (K x) a) where
  Rep Vector (K x Any)
v == :: Rep (K x) a -> Rep (K x) a -> Bool
== Rep Vector (K x Any)
v' =
         (K x Any -> x) -> [K x Any] -> [x]
forall a b. (a -> b) -> [a] -> [b]
Prelude.map K x Any -> x
forall k a (b :: k). K a b -> a
unK (Vector (K x Any) -> [K x Any]
forall a. Vector a -> [a]
V.toList Vector (K x Any)
v)
      [x] -> [x] -> Bool
forall a. Eq a => a -> a -> Bool
== (K x Any -> x) -> [K x Any] -> [x]
forall a b. (a -> b) -> [a] -> [b]
Prelude.map K x Any -> x
forall k a (b :: k). K a b -> a
unK (Vector (K x Any) -> [K x Any]
forall a. Vector a -> [a]
V.toList Vector (K x Any)
v')

{-------------------------------------------------------------------------------
  Internal utility
-------------------------------------------------------------------------------}

compileToHere :: Q [Dec]
compileToHere :: Q [Dec]
compileToHere = [Dec] -> Q [Dec]
forall (m :: Type -> Type) a. Monad m => a -> m a
return []