@@ -21,40 +21,96 @@ import Rel8.Expr.Opaleye ( mapPrimExpr, zipPrimExprsWith )
2121import Rel8.Expr.Serialize ( litExpr )
2222
2323
24+-- | The SQL @false@ literal.
2425false :: Expr Bool
2526false = litExpr False
2627
2728
29+-- | The SQL @true@ literal.
2830true :: Expr Bool
2931true = litExpr True
3032
3133
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)
3246(&&.) :: Expr Bool -> Expr Bool -> Expr Bool
3347(&&.) = zipPrimExprsWith (Opaleye.BinExpr Opaleye.OpAnd)
3448infixr 3 &&.
3549
3650
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)
3763(||.) :: Expr Bool -> Expr Bool -> Expr Bool
3864(||.) = zipPrimExprsWith (Opaleye.BinExpr Opaleye.OpOr)
3965infixr 2 ||.
4066
4167
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]
4275not_ :: Expr Bool -> Expr Bool
4376not_ = mapPrimExpr (Opaleye.UnExpr Opaleye.OpNot)
4477
4578
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]
4686and_ :: Foldable f => f (Expr Bool) -> Expr Bool
4787and_ = foldl' (&&.) true
4888
4989
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]
5097or_ :: Foldable f => f (Expr Bool) -> Expr Bool
5198or_ = foldl' (||.) false
5299
53100
101+-- | Eliminate a boolean-valued expression.
102+--
103+-- Corresponds to 'Data.Bool.bool'.
54104boolExpr :: Expr a -> Expr a -> Expr Bool -> Expr a
55105boolExpr ifFalse ifTrue condition = caseExpr [(condition, ifTrue)] ifFalse
56106
57107
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.
58114caseExpr :: [(Expr Bool, Expr a)] -> Expr a -> Expr a
59115caseExpr branches (Expr fallback) =
60116 Expr $ Opaleye.CaseExpr (map go branches) fallback