Comparison operators, like (.==), accepts aribtrary SqlType value.
(.==) :: (Same s t, SqlType a) => Col s a -> Col t a -> Col s Bool
Since Maybe Int is also an SqlTpye, the following code type checks.
But one of the operand is NULL, the result will be NULL, making the code crash.
test :: IO Bool
test = withSQLite "test.sqlite" $ do
[b] <- query $ pure $ just (4 :: Col s Int) .== literal Nothing
pure b
Using Nullable module's operator (?==) will get the proper result type Col s (Maybe Bool).
But the need to correctly use (.==) and (?==) is error-prone.
First thing that comes to my mind, is to add type IsNullable a :: 'Bool to SqlType type class.
SqlType (Maybe a) instance will be the only instance to have IsNullable (Maybe a) = 'True, and other instances will have False.Then we could wrap Bool with Maybe when SqlType is IsNullable.
Comparison operators, like
(.==)
, accepts aribtrarySqlType
value.Since
Maybe Int
is also anSqlTpye
, the following code type checks. But one of the operand isNULL
, the result will beNULL
, making the code crash.Using
Nullable
module's operator(?==)
will get the proper result typeCol s (Maybe Bool)
. But the need to correctly use(.==)
and(?==)
is error-prone.First thing that comes to my mind, is to add
type IsNullable a :: 'Bool
toSqlType
type class.SqlType (Maybe a)
instance will be the only instance to haveIsNullable (Maybe a) = 'True
, and other instances will haveFalse
.Then we could wrapBool
withMaybe
whenSqlType
isIsNullable
.