on da76712 help sign in
rel8/src/Rel8/Expr/Num.hs
110 lines 3.2 kB history raw
1{-# language FlexibleContexts #-}
2{-# language TypeFamilies #-}
4{-# options_ghc -fno-warn-redundant-constraints #-}
6module Rel8.Expr.Num
7 ( fromIntegral
8 , realToFrac
9 , div, mod, divMod
10 , quot, rem, quotRem
11 , ceiling, floor, round, truncate
12 )
13where
15-- base
16import Prelude ( (+), (-), fst, negate, signum, snd )
18-- rel
19import Rel8.Expr ( Expr( Expr ) )
20import Rel8.Expr.Eq ( (==.) )
21import Rel8.Expr.Function ( function )
22import Rel8.Expr.Opaleye ( castExpr )
23import Rel8.Schema.Null ( Homonullable, Sql )
24import Rel8.Table.Bool ( bool )
25import Rel8.Type.Num ( DBFractional, DBIntegral, DBNum )
28-- | Cast 'DBIntegral' types to 'DBNum' types. For example, this can be useful
29-- if you need to turn an @Expr Int32@ into an @Expr Double@.
30fromIntegral :: (Sql DBIntegral a, Sql DBNum b, Homonullable a b)
31 => Expr a -> Expr b
32fromIntegral (Expr a) = castExpr (Expr a)
35-- | Cast 'DBNum' types to 'DBFractional' types. For example, his can be useful
36-- to convert @Expr Float@ to @Expr Double@.
37realToFrac :: (Sql DBNum a, Sql DBFractional b, Homonullable a b)
38 => Expr a -> Expr b
39realToFrac (Expr a) = castExpr (Expr a)
42-- | Round a 'DBFractional' to a 'DBIntegral' by rounding to the nearest larger
43-- integer.
44--
45-- Corresponds to the @ceiling()@ function.
46ceiling :: (Sql DBFractional a, Sql DBIntegral b, Homonullable a b)
47 => Expr a -> Expr b
48ceiling = function "ceiling"
51-- | Emulates the behaviour of the Haskell function 'Prelude.div' in
52-- PostgreSQL.
53div :: Sql DBIntegral a => Expr a -> Expr a -> Expr a
54div n d = fst (divMod n d)
57-- | Emulates the behaviour of the Haskell function 'Prelude.mod' in
58-- PostgreSQL.
59mod :: Sql DBIntegral a => Expr a -> Expr a -> Expr a
60mod n d = snd (divMod n d)
63-- | Simultaneous 'div' and 'mod'.
64divMod :: Sql DBIntegral a => Expr a -> Expr a -> (Expr a, Expr a)
65divMod n d = bool qr (q - 1, r + d) (signum r ==. negate (signum d))
66 where
67 qr@(q, r) = quotRem n d
70-- | Perform integral division. Corresponds to the @div()@ function in
71-- PostgreSQL, which behaves like Haskell's 'Prelude.quot' rather than
72-- 'Prelude.div'.
73quot :: Sql DBIntegral a => Expr a -> Expr a -> Expr a
74quot = function "div"
77-- | Corresponds to the @mod()@ function in PostgreSQL, which behaves like
78-- Haskell's 'Prelude.rem' rather than 'Prelude.mod'.
79rem :: Sql DBIntegral a => Expr a -> Expr a -> Expr a
80rem = function "mod"
83-- | Simultaneous 'quot' and 'rem'.
84quotRem :: Sql DBIntegral a => Expr a -> Expr a -> (Expr a, Expr a)
85quotRem n d = (quot n d, rem n d)
88-- | Round a 'DFractional' to a 'DBIntegral' by rounding to the nearest smaller
89-- integer.
90--
91-- Corresponds to the @floor()@ function.
92floor :: (Sql DBFractional a, Sql DBIntegral b, Homonullable a b)
93 => Expr a -> Expr b
94floor = function "floor"
97-- | Round a 'DBFractional' to a 'DBIntegral' by rounding to the nearest
98-- integer.
99--
100-- Corresponds to the @round()@ function.
101round :: (Sql DBFractional a, Sql DBIntegral b, Homonullable a b)
102 => Expr a -> Expr b
103round = function "round"
106-- | Round a 'DBFractional' to a 'DBIntegral' by rounding to the nearest
107-- integer towards zero.
108truncate :: (Sql DBFractional a, Sql DBIntegral b, Homonullable a b)
109 => Expr a -> Expr b
110truncate = function "trunc"