{-# language DataKinds #-}
{-# language GADTs #-}
{-# language NamedFieldPuns #-}
{-# language StandaloneKindSignatures #-}
{-# language TypeFamilies #-}

module Rel8.Schema.Result
  ( Col( R, unR ), Result
  , relabel
  , null, nullifier, unnullifier
  , vectorizer, unvectorizer
  )
where

-- base
import Prelude hiding ( null )

-- rel8
import Rel8.Schema.Context ( Interpretation( Col ) )
import Rel8.Schema.HTable.Identity ( HIdentity(..) )
import Rel8.Schema.Kind ( Context )
import Rel8.Schema.Null ( Nullify, Nullity( Null, NotNull ) )
import Rel8.Schema.Spec ( Spec( Spec ), SSpec(..) )


-- | The @Result@ context is the context used for decoded query results.
--
-- When a query is executed against a PostgreSQL database, Rel8 parses the
-- returned rows, decoding each row into the @Result@ context.
type Result :: Context
data Result a


instance Interpretation Result where
  data Col Result _spec where
    R :: {Col Result ('Spec labels a) -> a
unR :: !a} -> Col Result ('Spec labels a)


relabel :: ()
  => HIdentity ('Spec labels a) (Col Result)
  -> HIdentity ('Spec relabels a) (Col Result)
relabel :: HIdentity ('Spec labels a) (Col Result)
-> HIdentity ('Spec relabels a) (Col Result)
relabel (HIdentity (R a)) = Col Result ('Spec relabels a)
-> HIdentity ('Spec relabels a) (Col Result)
forall (spec :: Spec) (context :: HContext).
context spec -> HIdentity spec context
HIdentity (a -> Col Result ('Spec relabels a)
forall a (labels :: Labels). a -> Col Result ('Spec labels a)
R a
a)


null :: Col Result ('Spec labels (Maybe a))
null :: Col Result ('Spec labels (Maybe a))
null = Maybe a -> Col Result ('Spec labels (Maybe a))
forall a (labels :: Labels). a -> Col Result ('Spec labels a)
R Maybe a
forall a. Maybe a
Nothing


nullifier :: ()
  => SSpec ('Spec labels a)
  -> Col Result ('Spec labels a)
  -> Col Result ('Spec labels (Nullify a))
nullifier :: SSpec ('Spec labels a)
-> Col Result ('Spec labels a)
-> Col Result ('Spec labels (Nullify a))
nullifier SSpec {Nullity a
nullity :: forall (labels :: Labels) a. SSpec ('Spec labels a) -> Nullity a
nullity :: Nullity a
nullity} (R a) = Nullify a -> Col Result ('Spec labels (Nullify a))
forall a (labels :: Labels). a -> Col Result ('Spec labels a)
R (Nullify a -> Col Result ('Spec labels (Nullify a)))
-> Nullify a -> Col Result ('Spec labels (Nullify a))
forall a b. (a -> b) -> a -> b
$ case Nullity a
nullity of
  Nullity a
Null -> a
Nullify a
a
  Nullity a
NotNull -> a -> Maybe a
forall a. a -> Maybe a
Just a
a


unnullifier :: ()
  => SSpec ('Spec labels a)
  -> Col Result ('Spec labels (Nullify a))
  -> Maybe (Col Result ('Spec labels a))
unnullifier :: SSpec ('Spec labels a)
-> Col Result ('Spec labels (Nullify a))
-> Maybe (Col Result ('Spec labels a))
unnullifier SSpec {Nullity a
nullity :: Nullity a
nullity :: forall (labels :: Labels) a. SSpec ('Spec labels a) -> Nullity a
nullity} (R a) =
  case Nullity a
nullity of
    Nullity a
Null -> Col Result ('Spec labels a) -> Maybe (Col Result ('Spec labels a))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Col Result ('Spec labels a)
 -> Maybe (Col Result ('Spec labels a)))
-> Col Result ('Spec labels a)
-> Maybe (Col Result ('Spec labels a))
forall a b. (a -> b) -> a -> b
$ a -> Col Result ('Spec labels a)
forall a (labels :: Labels). a -> Col Result ('Spec labels a)
R a
a
    Nullity a
NotNull -> a -> Col Result ('Spec labels a)
forall a (labels :: Labels). a -> Col Result ('Spec labels a)
R (a -> Col Result ('Spec labels a))
-> Maybe a -> Maybe (Col Result ('Spec labels a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a
Maybe a
a


vectorizer :: Functor f
  => SSpec ('Spec labels a)
  -> f (Col Result ('Spec labels a))
  -> Col Result ('Spec labels (f a))
vectorizer :: SSpec ('Spec labels a)
-> f (Col Result ('Spec labels a))
-> Col Result ('Spec labels (f a))
vectorizer SSpec ('Spec labels a)
_ = f a -> Col Result ('Spec labels (f a))
forall a (labels :: Labels). a -> Col Result ('Spec labels a)
R (f a -> Col Result ('Spec labels (f a)))
-> (f (Col Result ('Spec labels a)) -> f a)
-> f (Col Result ('Spec labels a))
-> Col Result ('Spec labels (f a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Col Result ('Spec labels a) -> a)
-> f (Col Result ('Spec labels a)) -> f a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Col Result ('Spec labels a) -> a
forall (labels :: Labels) a. Col Result ('Spec labels a) -> a
unR


unvectorizer :: Functor f
  => SSpec ('Spec labels a)
  -> Col Result ('Spec labels (f a))
  -> f (Col Result ('Spec labels a))
unvectorizer :: SSpec ('Spec labels a)
-> Col Result ('Spec labels (f a))
-> f (Col Result ('Spec labels a))
unvectorizer SSpec ('Spec labels a)
_ (R results) = a -> Col Result ('Spec labels a)
forall a (labels :: Labels). a -> Col Result ('Spec labels a)
R (a -> Col Result ('Spec labels a))
-> f a -> f (Col Result ('Spec labels a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a
f a
results