Nullable vs MaybeFields
stevemao opened this issue · comments
It is recommended to use MaybeFields
instead of NULL
. But FieldNullable
is using NULL
so converting between the two isn't avoidable which is quite annoying to the users. Is there a plan to make FieldNullable
to use MaybeFields
internally?
Could you give an example of what's annoying?
My understanding is when selecting a nullable field, I get Select FieldNullable a
, then I'll need to convert it to Select MaybeFields a
to be able to work with things like optionalRestrict
. What's the point of having two different types representing the same thing?
I see. It sounds like you are talking about fields that come from base tables, that you define with table
. Is that right? If so then how about a way of defining table fields that doesn't mention NULLABLE
fields in the first place, for example requiredTableMaybeField
, as defined below? Does that solve the problem? If not could you say a little more about the problem?
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
import Opaleye
import Data.Profunctor.Product.TH
import Data.Profunctor
requiredTableMaybeField ::
String ->
TableFields (MaybeFields (Field a)) (MaybeFields (Field a))
requiredTableMaybeField name =
dimap (\mf -> matchMaybe mf $ \case
Nothing -> Opaleye.null
Just x -> toNullable x)
nullableToMaybeFields
(requiredTableField name)
-- Example of using it
data Widget a b c = Widget { wid :: a
, color :: b
, location :: c
}
$(makeAdaptorAndInstance "pWidget" ''Widget)
widgetTableNullable ::
Table (Widget (Maybe (Field SqlInt4)) (Field SqlText) (FieldNullable SqlText))
(Widget (Field SqlInt4) (Field SqlText) (FieldNullable SqlText))
widgetTableNullable =
table "widgetTable"
(pWidget Widget { wid = optionalTableField "id"
, color = requiredTableField "color"
, location = requiredTableField "location"
})
widgetTableMaybe ::
Table (Widget (Maybe (Field SqlInt4)) (Field SqlText) (MaybeFields (Field SqlText)))
(Widget (Field SqlInt4) (Field SqlText) (MaybeFields (Field SqlText)))
widgetTableMaybe =
table "widgetTable"
(pWidget Widget { wid = optionalTableField "id"
, color = requiredTableField "color"
, location = requiredTableMaybeField "location"
})
Yes, this solves the problem! (though I haven't tried the code)
MaybeFields (Field SqlText)
instead of FieldNullable SqlText
seems much better. Do you think this should be the preferred way of defining nullable fields, and perhaps deprecate the other? If not, is there anything FieldNullable
can do but MaybeFields
can't?
Yes, this solves the problem! (though I haven't tried the code)
Cool! Please let me know your experience when you've tried it.
Some users may well want to handle nullability directly, but using MaybeFields
by default seems like a reasonable idea. I'll add requiredTableMaybeField
to the library at some point and suggest it in favour of nullable fields.
Cool! Please let me know your experience when you've tried it.
will do. We won't change it immediately as it's not a small codebase now...
Some users may well want to handle nullability directly
It seems that all functions working with nullable have an equivalent with MaybeFields
. Having 2 equivalent Maybe
types seems unnecessary. I'd only keep one in my codebase but I'll have to see how well it works.
Thanks again!
It seems that all functions working with nullable have an equivalent with MaybeFields. Having 2 equivalent Maybe types seems unnecessary. I'd only keep one in my codebase but I'll have to see how well it works.
Yes, I could replace all the nullable functionality with MaybeFields functionality. That would be much nicer from an API point of view. But it's possible that there will be a small performance impact to using MaybeFields.
Thanks again!
Happy to help! Please ask again any time.
Closing as inactive, but feel free to reopen if necessary.