{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}

module Opaleye.Internal.Values where

import           Opaleye.Internal.Column (Column(Column))
import qualified Opaleye.Internal.Unpackspec as U
import qualified Opaleye.Internal.Tag as T
import qualified Opaleye.Internal.PrimQuery as PQ
import qualified Opaleye.Internal.PackMap as PM
import qualified Opaleye.Internal.HaskellDB.PrimQuery as HPQ
import qualified Opaleye.Internal.PGTypes
import qualified Opaleye.SqlTypes

import           Data.Functor.Identity (runIdentity)
import qualified Data.List.NonEmpty as NEL
import           Data.Profunctor (Profunctor, dimap, rmap, lmap)
import           Data.Profunctor.Product (ProductProfunctor)
import qualified Data.Profunctor.Product as PP
import           Data.Profunctor.Product.Default (Default, def)

import           Control.Applicative (Applicative, pure, (<*>))

-- FIXME: We don't currently handle the case of zero columns.  Need to
-- emit a dummy column and data.
valuesU :: U.Unpackspec columns columns'
        -> ValuesspecUnsafe columns columns'
        -> [columns]
        -> ((), T.Tag) -> (columns', PQ.PrimQuery, T.Tag)
valuesU :: Unpackspec columns columns'
-> ValuesspecUnsafe columns columns'
-> [columns]
-> ((), Tag)
-> (columns', PrimQuery, Tag)
valuesU Unpackspec columns columns'
unpack ValuesspecUnsafe columns columns'
valuesspec [columns]
rows ((), Tag
t) = (columns'
newColumns, PrimQuery
primQ', Tag -> Tag
T.next Tag
t)
  where runRow :: columns -> [PrimExpr]
runRow columns
row = [PrimExpr]
valuesRow
           where (columns'
_, [PrimExpr]
valuesRow) =
                   PM [PrimExpr] columns' -> (columns', [PrimExpr])
forall a r. PM [a] r -> (r, [a])
PM.run (Unpackspec columns columns'
-> (PrimExpr -> StateT ([PrimExpr], Int) Identity PrimExpr)
-> columns
-> PM [PrimExpr] columns'
forall (f :: * -> *) columns b.
Applicative f =>
Unpackspec columns b -> (PrimExpr -> f PrimExpr) -> columns -> f b
U.runUnpackspec Unpackspec columns columns'
unpack PrimExpr -> StateT ([PrimExpr], Int) Identity PrimExpr
extractValuesEntry columns
row)

        (columns'
newColumns, [(Symbol, ())]
valuesPEs_nulls) =
          PM [(Symbol, ())] columns' -> (columns', [(Symbol, ())])
forall a r. PM [a] r -> (r, [a])
PM.run (ValuesspecUnsafe columns columns'
-> (() -> StateT ([(Symbol, ())], Int) Identity PrimExpr)
-> PM [(Symbol, ())] columns'
forall (f :: * -> *) columns columns'.
Applicative f =>
ValuesspecUnsafe columns columns'
-> (() -> f PrimExpr) -> f columns'
runValuesspec ValuesspecUnsafe columns columns'
valuesspec (Tag -> () -> StateT ([(Symbol, ())], Int) Identity PrimExpr
forall primExpr.
Tag -> primExpr -> PM [(Symbol, primExpr)] PrimExpr
extractValuesField Tag
t))

        valuesPEs :: [Symbol]
valuesPEs = ((Symbol, ()) -> Symbol) -> [(Symbol, ())] -> [Symbol]
forall a b. (a -> b) -> [a] -> [b]
map (Symbol, ()) -> Symbol
forall a b. (a, b) -> a
fst [(Symbol, ())]
valuesPEs_nulls

        values :: [[HPQ.PrimExpr]]
        values :: [[PrimExpr]]
values = (columns -> [PrimExpr]) -> [columns] -> [[PrimExpr]]
forall a b. (a -> b) -> [a] -> [b]
map columns -> [PrimExpr]
runRow [columns]
rows

        primQ' :: PrimQuery
primQ' = case [[PrimExpr]] -> Maybe (NonEmpty [PrimExpr])
forall a. [a] -> Maybe (NonEmpty a)
NEL.nonEmpty [[PrimExpr]]
values of
          Maybe (NonEmpty [PrimExpr])
Nothing      -> () -> PrimQuery
forall a. a -> PrimQuery' a
PQ.Empty ()
          Just NonEmpty [PrimExpr]
values' -> [Symbol] -> NonEmpty [PrimExpr] -> PrimQuery
forall a. [Symbol] -> NonEmpty [PrimExpr] -> PrimQuery' a
PQ.Values [Symbol]
valuesPEs NonEmpty [PrimExpr]
values'

-- We don't actually use the return value of this.  It might be better
-- to come up with another Applicative instance for specifically doing
-- what we need.
extractValuesEntry :: HPQ.PrimExpr -> PM.PM [HPQ.PrimExpr] HPQ.PrimExpr
extractValuesEntry :: PrimExpr -> StateT ([PrimExpr], Int) Identity PrimExpr
extractValuesEntry PrimExpr
pe = do
  PrimExpr -> PM [PrimExpr] ()
forall a. a -> PM [a] ()
PM.write PrimExpr
pe
  PrimExpr -> StateT ([PrimExpr], Int) Identity PrimExpr
forall (m :: * -> *) a. Monad m => a -> m a
return PrimExpr
pe

extractValuesField :: T.Tag -> primExpr
                   -> PM.PM [(HPQ.Symbol, primExpr)] HPQ.PrimExpr
extractValuesField :: Tag -> primExpr -> PM [(Symbol, primExpr)] PrimExpr
extractValuesField = String -> Tag -> primExpr -> PM [(Symbol, primExpr)] PrimExpr
forall primExpr.
String -> Tag -> primExpr -> PM [(Symbol, primExpr)] PrimExpr
PM.extractAttr String
"values"

newtype ValuesspecUnsafe columns columns' =
  Valuesspec (PM.PackMap () HPQ.PrimExpr () columns')

runValuesspec :: Applicative f => ValuesspecUnsafe columns columns'
              -> (() -> f HPQ.PrimExpr) -> f columns'
runValuesspec :: ValuesspecUnsafe columns columns'
-> (() -> f PrimExpr) -> f columns'
runValuesspec (Valuesspec PackMap () PrimExpr () columns'
v) () -> f PrimExpr
f = PackMap () PrimExpr () columns'
-> (() -> f PrimExpr) -> () -> f columns'
forall (f :: * -> *) a b s t.
Applicative f =>
PackMap a b s t -> (a -> f b) -> s -> f t
PM.traversePM PackMap () PrimExpr () columns'
v () -> f PrimExpr
f ()

instance Default ValuesspecUnsafe (Column a) (Column a) where
  def :: ValuesspecUnsafe (Column a) (Column a)
def = PackMap () PrimExpr () (Column a)
-> ValuesspecUnsafe (Column a) (Column a)
forall columns columns'.
PackMap () PrimExpr () columns'
-> ValuesspecUnsafe columns columns'
Valuesspec ((() -> ())
-> (PrimExpr -> Column a) -> PackMap () PrimExpr () (Column a)
forall s a b t. (s -> a) -> (b -> t) -> PackMap a b s t
PM.iso () -> ()
forall a. a -> a
id PrimExpr -> Column a
forall pgType. PrimExpr -> Column pgType
Column)

valuesUSafe :: Valuesspec columns columns'
            -> [columns]
            -> ((), T.Tag) -> (columns', PQ.PrimQuery, T.Tag)
valuesUSafe :: Valuesspec columns columns'
-> [columns] -> ((), Tag) -> (columns', PrimQuery, Tag)
valuesUSafe valuesspec :: Valuesspec columns columns'
valuesspec@(ValuesspecSafe PackMap PrimExpr PrimExpr () columns'
_ Unpackspec columns columns'
unpack) [columns]
rows ((), Tag
t) =
  (columns'
newColumns, PrimQuery
primQ', Tag -> Tag
T.next Tag
t)
  where runRow :: columns -> [PrimExpr]
runRow columns
row =
          case PM [PrimExpr] columns' -> (columns', [PrimExpr])
forall a r. PM [a] r -> (r, [a])
PM.run (Unpackspec columns columns'
-> (PrimExpr -> StateT ([PrimExpr], Int) Identity PrimExpr)
-> columns
-> PM [PrimExpr] columns'
forall (f :: * -> *) columns b.
Applicative f =>
Unpackspec columns b -> (PrimExpr -> f PrimExpr) -> columns -> f b
U.runUnpackspec Unpackspec columns columns'
unpack PrimExpr -> StateT ([PrimExpr], Int) Identity PrimExpr
extractValuesEntry columns
row) of
            (columns'
_, []) -> [PrimExpr
zero]
            (columns'
_, [PrimExpr]
xs) -> [PrimExpr]
xs

        (columns'
newColumns, [(Symbol, PrimExpr)]
valuesPEs_nulls) =
          PM [(Symbol, PrimExpr)] columns'
-> (columns', [(Symbol, PrimExpr)])
forall a r. PM [a] r -> (r, [a])
PM.run (Valuesspec columns columns'
-> (PrimExpr
    -> StateT ([(Symbol, PrimExpr)], Int) Identity PrimExpr)
-> PM [(Symbol, PrimExpr)] columns'
forall (f :: * -> *) columns columns'.
Applicative f =>
Valuesspec columns columns'
-> (PrimExpr -> f PrimExpr) -> f columns'
runValuesspecSafe Valuesspec columns columns'
valuesspec (Tag
-> PrimExpr -> StateT ([(Symbol, PrimExpr)], Int) Identity PrimExpr
forall primExpr.
Tag -> primExpr -> PM [(Symbol, primExpr)] PrimExpr
extractValuesField Tag
t))

        valuesPEs :: [Symbol]
valuesPEs = ((Symbol, PrimExpr) -> Symbol) -> [(Symbol, PrimExpr)] -> [Symbol]
forall a b. (a -> b) -> [a] -> [b]
map (Symbol, PrimExpr) -> Symbol
forall a b. (a, b) -> a
fst [(Symbol, PrimExpr)]
valuesPEs_nulls
        nulls :: [PrimExpr]
nulls = case ((Symbol, PrimExpr) -> PrimExpr)
-> [(Symbol, PrimExpr)] -> [PrimExpr]
forall a b. (a -> b) -> [a] -> [b]
map (Symbol, PrimExpr) -> PrimExpr
forall a b. (a, b) -> b
snd [(Symbol, PrimExpr)]
valuesPEs_nulls of
          []     -> [PrimExpr
nullInt]
          [PrimExpr]
nulls' -> [PrimExpr]
nulls'

        yieldNoRows :: PQ.PrimQuery -> PQ.PrimQuery
        yieldNoRows :: PrimQuery -> PrimQuery
yieldNoRows = PrimExpr -> PrimQuery -> PrimQuery
PQ.restrict (Literal -> PrimExpr
HPQ.ConstExpr (Bool -> Literal
HPQ.BoolLit Bool
False))

        zero :: PrimExpr
zero = Literal -> PrimExpr
HPQ.ConstExpr (Integer -> Literal
HPQ.IntegerLit Integer
0)
        nullInt :: PrimExpr
nullInt = String -> PrimExpr -> PrimExpr
HPQ.CastExpr (Maybe SqlInt4 -> String
forall sqlType (proxy :: * -> *).
IsSqlType sqlType =>
proxy sqlType -> String
Opaleye.Internal.PGTypes.showSqlType
                                  (Maybe SqlInt4
forall a. Maybe a
Nothing :: Maybe Opaleye.SqlTypes.SqlInt4))
                               (Literal -> PrimExpr
HPQ.ConstExpr Literal
HPQ.NullLit)

        (NonEmpty [PrimExpr]
values, PrimQuery -> PrimQuery
wrap) = case [columns] -> Maybe (NonEmpty columns)
forall a. [a] -> Maybe (NonEmpty a)
NEL.nonEmpty [columns]
rows of
          Maybe (NonEmpty columns)
Nothing    -> ([PrimExpr] -> NonEmpty [PrimExpr]
forall (f :: * -> *) a. Applicative f => a -> f a
pure [PrimExpr]
nulls, PrimQuery -> PrimQuery
yieldNoRows)
          Just NonEmpty columns
rows' -> ((columns -> [PrimExpr]) -> NonEmpty columns -> NonEmpty [PrimExpr]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap columns -> [PrimExpr]
runRow NonEmpty columns
rows', PrimQuery -> PrimQuery
forall a. a -> a
id)

        primQ' :: PrimQuery
primQ' = PrimQuery -> PrimQuery
wrap ([Symbol] -> NonEmpty [PrimExpr] -> PrimQuery
forall a. [Symbol] -> NonEmpty [PrimExpr] -> PrimQuery' a
PQ.Values [Symbol]
valuesPEs NonEmpty [PrimExpr]
values)

data Valuesspec columns columns' =
  ValuesspecSafe (PM.PackMap HPQ.PrimExpr HPQ.PrimExpr () columns')
                 (U.Unpackspec columns columns')

type ValuesspecSafe = Valuesspec

runValuesspecSafe :: Applicative f
                  => Valuesspec columns columns'
                  -> (HPQ.PrimExpr -> f HPQ.PrimExpr)
                  -> f columns'
runValuesspecSafe :: Valuesspec columns columns'
-> (PrimExpr -> f PrimExpr) -> f columns'
runValuesspecSafe (ValuesspecSafe PackMap PrimExpr PrimExpr () columns'
v Unpackspec columns columns'
_) PrimExpr -> f PrimExpr
f = PackMap PrimExpr PrimExpr () columns'
-> (PrimExpr -> f PrimExpr) -> () -> f columns'
forall (f :: * -> *) a b s t.
Applicative f =>
PackMap a b s t -> (a -> f b) -> s -> f t
PM.traversePM PackMap PrimExpr PrimExpr () columns'
v PrimExpr -> f PrimExpr
f ()

valuesspecField :: Opaleye.SqlTypes.IsSqlType a
                => Valuesspec (Column a) (Column a)
valuesspecField :: Valuesspec (Column a) (Column a)
valuesspecField = Valuesspec (Column a) (Column a)
forall (p :: * -> * -> *) a b. Default p a b => p a b
def

instance Opaleye.Internal.PGTypes.IsSqlType a
  => Default Valuesspec (Column a) (Column a) where
  def :: Valuesspec (Column a) (Column a)
def = Valuesspec (Column a) (Column a)
def_
    where def_ :: Valuesspec (Column a) (Column a)
def_ = PackMap PrimExpr PrimExpr () (Column a)
-> Unpackspec (Column a) (Column a)
-> Valuesspec (Column a) (Column a)
forall columns columns'.
PackMap PrimExpr PrimExpr () columns'
-> Unpackspec columns columns' -> Valuesspec columns columns'
ValuesspecSafe ((forall (f :: * -> *).
 Applicative f =>
 (PrimExpr -> f PrimExpr) -> () -> f (Column a))
-> PackMap PrimExpr PrimExpr () (Column a)
forall a b s t.
(forall (f :: * -> *). Applicative f => (a -> f b) -> s -> f t)
-> PackMap a b s t
PM.PackMap (\PrimExpr -> f PrimExpr
f () -> (PrimExpr -> Column a) -> f PrimExpr -> f (Column a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap PrimExpr -> Column a
forall pgType. PrimExpr -> Column pgType
Column (PrimExpr -> f PrimExpr
f PrimExpr
null_)))
                                Unpackspec (Column a) (Column a)
forall a. Unpackspec (Column a) (Column a)
U.unpackspecField
          null_ :: PrimExpr
null_ = Maybe a -> PrimExpr
forall a (proxy :: * -> *). IsSqlType a => proxy a -> PrimExpr
nullPE Maybe a
sqlType

          sqlType :: Maybe a
sqlType = Valuesspec (Column a) (Column a) -> Maybe a
forall (f :: * -> *) sqlType. f (Column sqlType) -> Maybe sqlType
columnProxy Valuesspec (Column a) (Column a)
def_
          columnProxy :: f (Column sqlType) -> Maybe sqlType
          columnProxy :: f (Column sqlType) -> Maybe sqlType
columnProxy f (Column sqlType)
_ = Maybe sqlType
forall a. Maybe a
Nothing

nullPE :: Opaleye.SqlTypes.IsSqlType a => proxy a -> HPQ.PrimExpr
nullPE :: proxy a -> PrimExpr
nullPE proxy a
sqlType = String -> PrimExpr -> PrimExpr
HPQ.CastExpr (proxy a -> String
forall sqlType (proxy :: * -> *).
IsSqlType sqlType =>
proxy sqlType -> String
Opaleye.Internal.PGTypes.showSqlType proxy a
sqlType)
                              (Literal -> PrimExpr
HPQ.ConstExpr Literal
HPQ.NullLit)

-- Implementing this in terms of Valuesspec for convenience
newtype Nullspec fields fields' = Nullspec (Valuesspec fields fields')

nullspecField :: Opaleye.SqlTypes.IsSqlType b
              => Nullspec a (Column b)
nullspecField :: Nullspec a (Column b)
nullspecField = Valuesspec a (Column b) -> Nullspec a (Column b)
forall fields fields'.
Valuesspec fields fields' -> Nullspec fields fields'
Nullspec ((a -> Column b)
-> Valuesspec (Column b) (Column b) -> Valuesspec a (Column b)
forall (p :: * -> * -> *) a b c.
Profunctor p =>
(a -> b) -> p b c -> p a c
lmap a -> Column b
forall a. a
e Valuesspec (Column b) (Column b)
forall a. IsSqlType a => Valuesspec (Column a) (Column a)
valuesspecField)
  where e :: a
e = String -> a
forall a. HasCallStack => String -> a
error ([String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ String
"We looked at the argument of a Nullspec when we "
                          , String
"expected that we never would!  This is a bug in "
                          , String
"Opaleye.  Please report it, if you can reproduce "
                          , String
"it."
                          ])

nullspecList :: Nullspec a [b]
nullspecList :: Nullspec a [b]
nullspecList = [b] -> Nullspec a [b]
forall (f :: * -> *) a. Applicative f => a -> f a
pure []

nullspecEitherLeft :: Nullspec a b
                   -> Nullspec a (Either b b')
nullspecEitherLeft :: Nullspec a b -> Nullspec a (Either b b')
nullspecEitherLeft = (b -> Either b b') -> Nullspec a b -> Nullspec a (Either b b')
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap b -> Either b b'
forall a b. a -> Either a b
Left

nullspecEitherRight :: Nullspec a b'
                    -> Nullspec a (Either b b')
nullspecEitherRight :: Nullspec a b' -> Nullspec a (Either b b')
nullspecEitherRight = (b' -> Either b b') -> Nullspec a b' -> Nullspec a (Either b b')
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap b' -> Either b b'
forall a b. b -> Either a b
Right

instance Opaleye.SqlTypes.IsSqlType b
  => Default Nullspec a (Column b) where
  def :: Nullspec a (Column b)
def = Nullspec a (Column b)
forall b a. IsSqlType b => Nullspec a (Column b)
nullspecField

-- | All fields @NULL@, even though technically the type may forbid
-- that!  Used to create such fields when we know we will never look
-- at them expecting to find something non-NULL.
nullFields :: Nullspec a fields -> fields
nullFields :: Nullspec a fields -> fields
nullFields (Nullspec Valuesspec a fields
v) = Identity fields -> fields
forall a. Identity a -> a
runIdentity (Valuesspec a fields
-> (PrimExpr -> Identity PrimExpr) -> Identity fields
forall (f :: * -> *) columns columns'.
Applicative f =>
Valuesspec columns columns'
-> (PrimExpr -> f PrimExpr) -> f columns'
runValuesspecSafe Valuesspec a fields
v PrimExpr -> Identity PrimExpr
forall (f :: * -> *) a. Applicative f => a -> f a
pure)

-- {

-- Boilerplate instance definitions.  Theoretically, these are derivable.

instance Functor (ValuesspecUnsafe a) where
  fmap :: (a -> b) -> ValuesspecUnsafe a a -> ValuesspecUnsafe a b
fmap a -> b
f (Valuesspec PackMap () PrimExpr () a
g) = PackMap () PrimExpr () b -> ValuesspecUnsafe a b
forall columns columns'.
PackMap () PrimExpr () columns'
-> ValuesspecUnsafe columns columns'
Valuesspec ((a -> b) -> PackMap () PrimExpr () a -> PackMap () PrimExpr () b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f PackMap () PrimExpr () a
g)

instance Applicative (ValuesspecUnsafe a) where
  pure :: a -> ValuesspecUnsafe a a
pure = PackMap () PrimExpr () a -> ValuesspecUnsafe a a
forall columns columns'.
PackMap () PrimExpr () columns'
-> ValuesspecUnsafe columns columns'
Valuesspec (PackMap () PrimExpr () a -> ValuesspecUnsafe a a)
-> (a -> PackMap () PrimExpr () a) -> a -> ValuesspecUnsafe a a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> PackMap () PrimExpr () a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
  Valuesspec PackMap () PrimExpr () (a -> b)
f <*> :: ValuesspecUnsafe a (a -> b)
-> ValuesspecUnsafe a a -> ValuesspecUnsafe a b
<*> Valuesspec PackMap () PrimExpr () a
x = PackMap () PrimExpr () b -> ValuesspecUnsafe a b
forall columns columns'.
PackMap () PrimExpr () columns'
-> ValuesspecUnsafe columns columns'
Valuesspec (PackMap () PrimExpr () (a -> b)
f PackMap () PrimExpr () (a -> b)
-> PackMap () PrimExpr () a -> PackMap () PrimExpr () b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> PackMap () PrimExpr () a
x)

instance Profunctor ValuesspecUnsafe where
  dimap :: (a -> b)
-> (c -> d) -> ValuesspecUnsafe b c -> ValuesspecUnsafe a d
dimap a -> b
_ c -> d
g (Valuesspec PackMap () PrimExpr () c
q) = PackMap () PrimExpr () d -> ValuesspecUnsafe a d
forall columns columns'.
PackMap () PrimExpr () columns'
-> ValuesspecUnsafe columns columns'
Valuesspec ((c -> d) -> PackMap () PrimExpr () c -> PackMap () PrimExpr () d
forall (p :: * -> * -> *) b c a.
Profunctor p =>
(b -> c) -> p a b -> p a c
rmap c -> d
g PackMap () PrimExpr () c
q)

instance ProductProfunctor ValuesspecUnsafe where
  purePP :: b -> ValuesspecUnsafe a b
purePP = b -> ValuesspecUnsafe a b
forall (f :: * -> *) a. Applicative f => a -> f a
pure
  **** :: ValuesspecUnsafe a (b -> c)
-> ValuesspecUnsafe a b -> ValuesspecUnsafe a c
(****) = ValuesspecUnsafe a (b -> c)
-> ValuesspecUnsafe a b -> ValuesspecUnsafe a c
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
(<*>)

instance Functor (Valuesspec a) where
  fmap :: (a -> b) -> Valuesspec a a -> Valuesspec a b
fmap a -> b
f (ValuesspecSafe PackMap PrimExpr PrimExpr () a
g Unpackspec a a
h) = PackMap PrimExpr PrimExpr () b -> Unpackspec a b -> Valuesspec a b
forall columns columns'.
PackMap PrimExpr PrimExpr () columns'
-> Unpackspec columns columns' -> Valuesspec columns columns'
ValuesspecSafe ((a -> b)
-> PackMap PrimExpr PrimExpr () a -> PackMap PrimExpr PrimExpr () b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f PackMap PrimExpr PrimExpr () a
g) ((a -> b) -> Unpackspec a a -> Unpackspec a b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f Unpackspec a a
h)

instance Applicative (Valuesspec a) where
  pure :: a -> Valuesspec a a
pure a
a = PackMap PrimExpr PrimExpr () a -> Unpackspec a a -> Valuesspec a a
forall columns columns'.
PackMap PrimExpr PrimExpr () columns'
-> Unpackspec columns columns' -> Valuesspec columns columns'
ValuesspecSafe (a -> PackMap PrimExpr PrimExpr () a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
a) (a -> Unpackspec a a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
a)
  ValuesspecSafe PackMap PrimExpr PrimExpr () (a -> b)
f Unpackspec a (a -> b)
f' <*> :: Valuesspec a (a -> b) -> Valuesspec a a -> Valuesspec a b
<*> ValuesspecSafe PackMap PrimExpr PrimExpr () a
x Unpackspec a a
x' =
    PackMap PrimExpr PrimExpr () b -> Unpackspec a b -> Valuesspec a b
forall columns columns'.
PackMap PrimExpr PrimExpr () columns'
-> Unpackspec columns columns' -> Valuesspec columns columns'
ValuesspecSafe (PackMap PrimExpr PrimExpr () (a -> b)
f PackMap PrimExpr PrimExpr () (a -> b)
-> PackMap PrimExpr PrimExpr () a -> PackMap PrimExpr PrimExpr () b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> PackMap PrimExpr PrimExpr () a
x) (Unpackspec a (a -> b)
f' Unpackspec a (a -> b) -> Unpackspec a a -> Unpackspec a b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Unpackspec a a
x')

instance Profunctor Valuesspec where
  dimap :: (a -> b) -> (c -> d) -> Valuesspec b c -> Valuesspec a d
dimap a -> b
f c -> d
g (ValuesspecSafe PackMap PrimExpr PrimExpr () c
q Unpackspec b c
q') = PackMap PrimExpr PrimExpr () d -> Unpackspec a d -> Valuesspec a d
forall columns columns'.
PackMap PrimExpr PrimExpr () columns'
-> Unpackspec columns columns' -> Valuesspec columns columns'
ValuesspecSafe ((c -> d)
-> PackMap PrimExpr PrimExpr () c -> PackMap PrimExpr PrimExpr () d
forall (p :: * -> * -> *) b c a.
Profunctor p =>
(b -> c) -> p a b -> p a c
rmap c -> d
g PackMap PrimExpr PrimExpr () c
q) ((a -> b) -> (c -> d) -> Unpackspec b c -> Unpackspec a d
forall (p :: * -> * -> *) a b c d.
Profunctor p =>
(a -> b) -> (c -> d) -> p b c -> p a d
dimap a -> b
f c -> d
g Unpackspec b c
q')

instance ProductProfunctor Valuesspec where
  purePP :: b -> Valuesspec a b
purePP = b -> Valuesspec a b
forall (f :: * -> *) a. Applicative f => a -> f a
pure
  **** :: Valuesspec a (b -> c) -> Valuesspec a b -> Valuesspec a c
(****) = Valuesspec a (b -> c) -> Valuesspec a b -> Valuesspec a c
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
(<*>)

instance Functor (Nullspec a) where
  fmap :: (a -> b) -> Nullspec a a -> Nullspec a b
fmap a -> b
f (Nullspec Valuesspec a a
g) = Valuesspec a b -> Nullspec a b
forall fields fields'.
Valuesspec fields fields' -> Nullspec fields fields'
Nullspec ((a -> b) -> Valuesspec a a -> Valuesspec a b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f Valuesspec a a
g)

instance Applicative (Nullspec a) where
  pure :: a -> Nullspec a a
pure = Valuesspec a a -> Nullspec a a
forall fields fields'.
Valuesspec fields fields' -> Nullspec fields fields'
Nullspec (Valuesspec a a -> Nullspec a a)
-> (a -> Valuesspec a a) -> a -> Nullspec a a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Valuesspec a a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
  Nullspec Valuesspec a (a -> b)
f <*> :: Nullspec a (a -> b) -> Nullspec a a -> Nullspec a b
<*> Nullspec Valuesspec a a
x = Valuesspec a b -> Nullspec a b
forall fields fields'.
Valuesspec fields fields' -> Nullspec fields fields'
Nullspec (Valuesspec a (a -> b)
f Valuesspec a (a -> b) -> Valuesspec a a -> Valuesspec a b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Valuesspec a a
x)

instance Profunctor Nullspec where
  dimap :: (a -> b) -> (c -> d) -> Nullspec b c -> Nullspec a d
dimap a -> b
f c -> d
g (Nullspec Valuesspec b c
q) = Valuesspec a d -> Nullspec a d
forall fields fields'.
Valuesspec fields fields' -> Nullspec fields fields'
Nullspec ((a -> b) -> (c -> d) -> Valuesspec b c -> Valuesspec a d
forall (p :: * -> * -> *) a b c d.
Profunctor p =>
(a -> b) -> (c -> d) -> p b c -> p a d
dimap a -> b
f c -> d
g Valuesspec b c
q)

instance ProductProfunctor Nullspec where
  purePP :: b -> Nullspec a b
purePP = b -> Nullspec a b
forall (f :: * -> *) a. Applicative f => a -> f a
pure
  **** :: Nullspec a (b -> c) -> Nullspec a b -> Nullspec a c
(****) = Nullspec a (b -> c) -> Nullspec a b -> Nullspec a c
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
(<*>)

-- }