on 11bcbbb help sign in
rel8/src/Rel8/Expr/Bool.hs
124 lines 3.0 kB history raw
1module Rel8.Expr.Bool
2 ( false, true
3 , (&&.), (||.), not_
4 , and_, or_
5 , boolExpr
6 , caseExpr
7 , coalesce
8 )
9where
11-- base
12import Data.Foldable ( foldl' )
13import Prelude hiding ( null )
15-- opaleye
16import qualified Opaleye.Internal.HaskellDB.PrimQuery as Opaleye
18-- rel8
19import {-# SOURCE #-} Rel8.Expr ( Expr( Expr ) )
20import Rel8.Expr.Opaleye ( mapPrimExpr, zipPrimExprsWith )
21import Rel8.Expr.Serialize ( litExpr )
24-- | The SQL @false@ literal.
25false :: Expr Bool
26false = litExpr False
29-- | The SQL @true@ literal.
30true :: Expr Bool
31true = litExpr True
34-- | The SQL @AND@ operator.
35--
36-- >>> :{
37-- mapM_ print =<< select c do
38-- x <- values [lit True, lit False]
39-- y <- values [lit True, lit False]
40-- return (x, y, x &&. y)
41-- :}
42-- (True,True,True)
43-- (True,False,False)
44-- (False,True,False)
45-- (False,False,False)
46(&&.) :: Expr Bool -> Expr Bool -> Expr Bool
47(&&.) = zipPrimExprsWith (Opaleye.BinExpr Opaleye.OpAnd)
48infixr 3 &&.
51-- | The SQL @OR@ operator.
52--
53-- >>> :{
54-- mapM_ print =<< select c do
55-- x <- values [lit True, lit False]
56-- y <- values [lit True, lit False]
57-- return (x, y, x ||. y)
58-- :}
59-- (True,True,True)
60-- (True,False,True)
61-- (False,True,True)
62-- (False,False,False)
63(||.) :: Expr Bool -> Expr Bool -> Expr Bool
64(||.) = zipPrimExprsWith (Opaleye.BinExpr Opaleye.OpOr)
65infixr 2 ||.
68-- | The SQL @NOT@ operator.
69--
70-- >>> select c $ pure $ not_ $ lit True
71-- [False]
72--
73-- >>> select c $ pure $ not_ $ lit False
74-- [True]
75not_ :: Expr Bool -> Expr Bool
76not_ = mapPrimExpr (Opaleye.UnExpr Opaleye.OpNot)
79-- | Fold @AND@ over a collection of expressions.
80--
81-- >>> select c $ pure $ and_ [ lit True ==. lit False, lit False, lit True ]
82-- [False]
83--
84-- >>> select c $ pure $ and_ []
85-- [True]
86and_ :: Foldable f => f (Expr Bool) -> Expr Bool
87and_ = foldl' (&&.) true
90-- | Fold @OR@ over a collection of expressions.
91--
92-- >>> select c $ pure $ or_ [ lit True ==. lit False, lit False, lit True ]
93-- [True]
94--
95-- >>> select c $ pure $ or_ []
96-- [False]
97or_ :: Foldable f => f (Expr Bool) -> Expr Bool
98or_ = foldl' (||.) false
101-- | Eliminate a boolean-valued expression.
102--
103-- Corresponds to 'Data.Bool.bool'.
104boolExpr :: Expr a -> Expr a -> Expr Bool -> Expr a
105boolExpr ifFalse ifTrue condition = caseExpr [(condition, ifTrue)] ifFalse
108-- | A multi-way if/then/else statement. The first argument to @caseExpr@ is a
109-- list of alternatives. The first alternative that is of the form @(true, x)@
110-- will be returned. If no such alternative is found, a fallback expression is
111-- returned.
112--
113-- Corresponds to a @CASE@ expression in SQL.
114caseExpr :: [(Expr Bool, Expr a)] -> Expr a -> Expr a
115caseExpr branches (Expr fallback) =
116 Expr $ Opaleye.CaseExpr (map go branches) fallback
117 where
118 go (Expr condition, Expr value) = (condition, value)
121coalesce :: Expr (Maybe Bool) -> Expr Bool
122coalesce (Expr a) = Expr a &&. Expr (Opaleye.FunExpr "COALESCE" [a, untrue])
123 where
124 untrue = Opaleye.ConstExpr (Opaleye.BoolLit False)