on 8a680c9 help sign in
rel8/src/Rel8/Expr/Bool.hs
90 lines 2.4 kB history raw
1{-# language GADTs #-}
3module Rel8.Expr.Bool
4 ( false, true
5 , (&&.), (||.), not_
6 , and_, or_
7 , boolExpr
8 , caseExpr
9 , coalesce
10 )
11where
13-- base
14import Data.Foldable ( foldl' )
15import Prelude hiding ( null )
17-- opaleye
18import qualified Opaleye.Internal.HaskellDB.PrimQuery as Opaleye
20-- rel8
21import {-# SOURCE #-} Rel8.Expr ( Expr( Expr ) )
22import Rel8.Expr.Opaleye ( mapPrimExpr, toPrimExpr, zipPrimExprsWith )
23import Rel8.Expr.Serialize ( litExpr )
26-- | The SQL @false@ literal.
27false :: Expr Bool
28false = litExpr False
31-- | The SQL @true@ literal.
32true :: Expr Bool
33true = litExpr True
36-- | The SQL @AND@ operator.
37(&&.) :: Expr Bool -> Expr Bool -> Expr Bool
38(&&.) = zipPrimExprsWith (Opaleye.BinExpr Opaleye.OpAnd)
39infixr 3 &&.
42-- | The SQL @OR@ operator.
43(||.) :: Expr Bool -> Expr Bool -> Expr Bool
44(||.) = zipPrimExprsWith (Opaleye.BinExpr Opaleye.OpOr)
45infixr 2 ||.
48-- | The SQL @NOT@ operator.
49not_ :: Expr Bool -> Expr Bool
50not_ = mapPrimExpr (Opaleye.UnExpr Opaleye.OpNot)
53-- | Fold @AND@ over a collection of expressions.
54and_ :: Foldable f => f (Expr Bool) -> Expr Bool
55and_ = foldl' (&&.) true
58-- | Fold @OR@ over a collection of expressions.
59or_ :: Foldable f => f (Expr Bool) -> Expr Bool
60or_ = foldl' (||.) false
63-- | Eliminate a boolean-valued expression.
64--
65-- Corresponds to 'Data.Bool.bool'.
66boolExpr :: Expr a -> Expr a -> Expr Bool -> Expr a
67boolExpr ifFalse ifTrue condition = caseExpr [(condition, ifTrue)] ifFalse
70-- | A multi-way if/then/else statement. The first argument to @caseExpr@ is a
71-- list of alternatives. The first alternative that is of the form @(true, x)@
72-- will be returned. If no such alternative is found, a fallback expression is
73-- returned.
74--
75-- Corresponds to a @CASE@ expression in SQL.
76caseExpr :: [(Expr Bool, Expr a)] -> Expr a -> Expr a
77caseExpr branches (Expr fallback) =
78 Expr $ Opaleye.CaseExpr (map go branches) fallback
79 where
80 go (condition, value) = (toPrimExpr condition, toPrimExpr value)
83-- | Convert a @Expr (Maybe Bool)@ to a @Expr Bool@ by treating @Nothing@ as
84-- @False@. This can be useful when combined with 'Rel8.where_', which expects
85-- a @Bool@, and produces expressions that optimize better than general case
86-- analysis.
87coalesce :: Expr (Maybe Bool) -> Expr Bool
88coalesce (Expr a) = Expr a &&. Expr (Opaleye.FunExpr "COALESCE" [a, untrue])
89 where
90 untrue = Opaleye.ConstExpr (Opaleye.BoolLit False)