{-# language BlockArguments #-}
{-# language DataKinds #-}
{-# language FlexibleContexts #-}
{-# language FlexibleInstances #-}
{-# language MultiParamTypeClasses #-}
{-# language StandaloneKindSignatures #-}
{-# language TypeFamilies #-}
{-# language UndecidableInstances #-}

module Rel8.Type.Semigroup
  ( DBSemigroup( (<>.))
  )
where

-- base
import Data.Kind ( Constraint, Type )
import Data.List.NonEmpty ( NonEmpty )
import Prelude ()

-- bytestring
import Data.ByteString ( ByteString )
import qualified Data.ByteString.Lazy as Lazy ( ByteString )

-- case-insensitive
import Data.CaseInsensitive ( CI )

-- opaleye
import qualified Opaleye.Internal.HaskellDB.PrimQuery as Opaleye

-- rel8
import {-# SOURCE #-} Rel8.Expr ( Expr )
import Rel8.Expr.Array ( sappend, sappend1 )
import Rel8.Expr.Opaleye ( zipPrimExprsWith )
import Rel8.Schema.Null ( Sql )
import Rel8.Type ( DBType )

-- text
import Data.Text ( Text )
import qualified Data.Text.Lazy as Lazy ( Text )

-- time
import Data.Time.LocalTime ( CalendarDiffTime )


-- | The class of 'Rel8.DBType's that form a semigroup. This class is purely a
-- Rel8 concept, and exists to mirror the 'Semigroup' class.
type DBSemigroup :: Type -> Constraint
class DBType a => DBSemigroup a where
  -- | An associative operation.
  (<>.) :: Expr a -> Expr a -> Expr a
  infixr 6 <>.


instance Sql DBType a => DBSemigroup [a] where
  <>. :: Expr [a] -> Expr [a] -> Expr [a]
(<>.) = Expr [a] -> Expr [a] -> Expr [a]
forall a. Expr [a] -> Expr [a] -> Expr [a]
sappend


instance Sql DBType a => DBSemigroup (NonEmpty a) where
  <>. :: Expr (NonEmpty a) -> Expr (NonEmpty a) -> Expr (NonEmpty a)
(<>.) = Expr (NonEmpty a) -> Expr (NonEmpty a) -> Expr (NonEmpty a)
forall a.
Expr (NonEmpty a) -> Expr (NonEmpty a) -> Expr (NonEmpty a)
sappend1


instance DBSemigroup CalendarDiffTime where
  <>. :: Expr CalendarDiffTime
-> Expr CalendarDiffTime -> Expr CalendarDiffTime
(<>.) = (PrimExpr -> PrimExpr -> PrimExpr)
-> Expr CalendarDiffTime
-> Expr CalendarDiffTime
-> Expr CalendarDiffTime
forall a b c.
(PrimExpr -> PrimExpr -> PrimExpr) -> Expr a -> Expr b -> Expr c
zipPrimExprsWith (BinOp -> PrimExpr -> PrimExpr -> PrimExpr
Opaleye.BinExpr BinOp
(Opaleye.:+))


instance DBSemigroup Text where
  <>. :: Expr Text -> Expr Text -> Expr Text
(<>.) = (PrimExpr -> PrimExpr -> PrimExpr)
-> Expr Text -> Expr Text -> Expr Text
forall a b c.
(PrimExpr -> PrimExpr -> PrimExpr) -> Expr a -> Expr b -> Expr c
zipPrimExprsWith (BinOp -> PrimExpr -> PrimExpr -> PrimExpr
Opaleye.BinExpr BinOp
(Opaleye.:||))


instance DBSemigroup Lazy.Text where
  <>. :: Expr Text -> Expr Text -> Expr Text
(<>.) = (PrimExpr -> PrimExpr -> PrimExpr)
-> Expr Text -> Expr Text -> Expr Text
forall a b c.
(PrimExpr -> PrimExpr -> PrimExpr) -> Expr a -> Expr b -> Expr c
zipPrimExprsWith (BinOp -> PrimExpr -> PrimExpr -> PrimExpr
Opaleye.BinExpr BinOp
(Opaleye.:||))


instance DBSemigroup (CI Text) where
  <>. :: Expr (CI Text) -> Expr (CI Text) -> Expr (CI Text)
(<>.) = (PrimExpr -> PrimExpr -> PrimExpr)
-> Expr (CI Text) -> Expr (CI Text) -> Expr (CI Text)
forall a b c.
(PrimExpr -> PrimExpr -> PrimExpr) -> Expr a -> Expr b -> Expr c
zipPrimExprsWith (BinOp -> PrimExpr -> PrimExpr -> PrimExpr
Opaleye.BinExpr BinOp
(Opaleye.:||))


instance DBSemigroup (CI Lazy.Text) where
  <>. :: Expr (CI Text) -> Expr (CI Text) -> Expr (CI Text)
(<>.) = (PrimExpr -> PrimExpr -> PrimExpr)
-> Expr (CI Text) -> Expr (CI Text) -> Expr (CI Text)
forall a b c.
(PrimExpr -> PrimExpr -> PrimExpr) -> Expr a -> Expr b -> Expr c
zipPrimExprsWith (BinOp -> PrimExpr -> PrimExpr -> PrimExpr
Opaleye.BinExpr BinOp
(Opaleye.:||))


instance DBSemigroup ByteString where
  <>. :: Expr ByteString -> Expr ByteString -> Expr ByteString
(<>.) = (PrimExpr -> PrimExpr -> PrimExpr)
-> Expr ByteString -> Expr ByteString -> Expr ByteString
forall a b c.
(PrimExpr -> PrimExpr -> PrimExpr) -> Expr a -> Expr b -> Expr c
zipPrimExprsWith (BinOp -> PrimExpr -> PrimExpr -> PrimExpr
Opaleye.BinExpr BinOp
(Opaleye.:||))


instance DBSemigroup Lazy.ByteString where
  <>. :: Expr ByteString -> Expr ByteString -> Expr ByteString
(<>.) = (PrimExpr -> PrimExpr -> PrimExpr)
-> Expr ByteString -> Expr ByteString -> Expr ByteString
forall a b c.
(PrimExpr -> PrimExpr -> PrimExpr) -> Expr a -> Expr b -> Expr c
zipPrimExprsWith (BinOp -> PrimExpr -> PrimExpr -> PrimExpr
Opaleye.BinExpr BinOp
(Opaleye.:||))