on 00a36f5 help sign in
rel8/src/Rel8/Type/Eq.hs
109 lines 3.0 kB history raw
1{-# language FlexibleContexts #-}
2{-# language FlexibleInstances #-}
3{-# language StandaloneKindSignatures #-}
4{-# language UndecidableInstances #-}
6module Rel8.Type.Eq
7 ( DBEq
8 )
9where
11-- aeson
12import Data.Aeson ( Value )
14-- base
15import Data.List.NonEmpty ( NonEmpty )
16import Data.Int ( Int16, Int32, Int64 )
17import Data.Kind ( Constraint, Type )
18import Prelude
20-- bytestring
21import Data.ByteString ( ByteString )
22import qualified Data.ByteString.Lazy as Lazy ( ByteString )
24-- case-insensitive
25import Data.CaseInsensitive ( CI )
27-- rel8
28import Rel8.Opaque ( Opaque )
29import Rel8.Schema.Nullability ( Sql )
30import Rel8.Type ( DBType )
32-- scientific
33import Data.Scientific ( Scientific )
35-- text
36import Data.Text ( Text )
37import qualified Data.Text.Lazy as Lazy ( Text )
39-- time
40import Data.Time.Calendar ( Day )
41import Data.Time.Clock ( UTCTime, DiffTime, NominalDiffTime )
42import Data.Time.LocalTime ( TimeOfDay, LocalTime )
44-- uuid
45import Data.UUID ( UUID )
48-- | Database types that can be compared for equality in queries. If a type is
49-- an instance of 'DBEq', it means we can compare expressions for equality
50-- using the SQL @=@ operator.
51--
52-- [ @DBEq@ with @newtype@s ]
53--
54-- Like with 'Rel8.DBType', @DBEq@ plays well with generalized newtype
55-- deriving. The example given for @DBType@ added a @UserId@ @newtype@, but
56-- without a @DBEq@ instance won't actually be able to use that in joins or
57-- where-clauses, because it lacks equality. We can add this by changing our
58-- @newtype@ definition to:
59--
60-- >>> newtype UserId = UserId { toInt32 :: Int32 } deriving newtype (DBType, DBEq)
61--
62-- This will re-use the equality logic for @Int32@, which is to just use the
63-- @=@ operator.
64--
65-- [ @DBEq@ with @DeriveAnyType@ ]
66--
67-- You can also use @DBEq@ with the @DeriveAnyType@ extension to easily add
68-- equality to your type, assuming that @=@ is sufficient on @DBType@ encoded
69-- values. Extending the example from 'Rel8.ReadShow''s 'Rel8.DBType' instance,
70-- we could add equality to @Color@ by writing:
71--
72-- >>> :{
73-- data Color = Red | Green | Blue | Purple | Gold
74-- deriving (Generic, Show, Read, DBEq)
75-- deriving DBType via ReadShow Color
76-- :}
77--
78-- This means @Color@s will be treated as the literal strings @"Red"@,
79-- @"Green"@, etc, in the database, and they can be compared for equality by
80-- just using @=@.
81type DBEq :: Type -> Constraint
82class DBType a => DBEq a
85instance DBEq Bool
86instance DBEq Char
87instance DBEq Int16
88instance DBEq Int32
89instance DBEq Int64
90instance DBEq Float
91instance DBEq Double
92instance DBEq Scientific
93instance DBEq UTCTime
94instance DBEq Day
95instance DBEq LocalTime
96instance DBEq TimeOfDay
97instance DBEq DiffTime
98instance DBEq NominalDiffTime
99instance DBEq Text
100instance DBEq Lazy.Text
101instance DBEq (CI Text)
102instance DBEq (CI Lazy.Text)
103instance DBEq ByteString
104instance DBEq Lazy.ByteString
105instance DBEq UUID
106instance DBEq Value
107instance Sql DBEq a => DBEq [a]
108instance Sql DBEq a => DBEq (NonEmpty a)
109instance DBEq Opaque