-
Notifications
You must be signed in to change notification settings - Fork 33
Open
Labels
Description
Hi,
I'm trying to factorize some of my row decoding code and I'm wondering if something like the following is possible.
The following currently doesn't work because of overlapping instances (and maybe further errors down the road).
decodeUser ::
forall pfx.
( KnownSymbol (AppendSymbol pfx "uid"),
KnownSymbol (AppendSymbol pfx "email"),
KnownSymbol (AppendSymbol pfx "fullname"),
KnownSymbol (AppendSymbol pfx "position"),
KnownSymbol (AppendSymbol pfx "location")
) =>
DecodeRow
'[ (AppendSymbol pfx "uid") ::: 'NotNull 'PGuuid,
(AppendSymbol pfx "email") ::: 'NotNull 'PGtext,
(AppendSymbol pfx "fullname") ::: 'NotNull 'PGtext,
(AppendSymbol pfx "position") ::: 'Null 'PGtext,
(AppendSymbol pfx "location") ::: 'Null 'PGtext
]
User
decodeUser = do
userId :: UserId <- fromLabel @(AppendSymbol pfx "uid")
email <- unsafeAddress <$> fromLabel @(AppendSymbol pfx "email")
fullName :: FullName <- fromLabel @(AppendSymbol pfx "fullname")
position <- fromLabel @(AppendSymbol pfx "position")
location <- fromLabel @(AppendSymbol pfx "location")
pure $ User userId email $ PersonalInfo fullName (fromMaybe "" position) (fromMaybe "" location)With the following schema
type UserTable =
'[ "user_pk" ::: 'PrimaryKey '["uid"],
"user_uk_email" ::: 'Unique '["email"],
"user_fk_picture" ::: 'ForeignKey '["picture"] "public" "file" '["uid"]
]
:=> '[ "uid" ::: 'NoDef :=> 'NotNull 'PGuuid,
"email" ::: 'NoDef :=> 'NotNull 'PGtext,
"created_at" ::: 'NoDef :=> 'NotNull 'PGtimestamptz,
"updated_at" ::: 'NoDef :=> 'NotNull 'PGtimestamptz,
"fullname" ::: 'NoDef :=> 'NotNull 'PGtext,
"picture" ::: 'NoDef :=> 'Null 'PGuuid,
"position" ::: 'NoDef :=> 'Null 'PGtext,
"location" ::: 'NoDef :=> 'Null 'PGtext
]And the following type
data User = User
{ id :: UserId,
email :: EmailAddress,
info :: PersonalInfo
}The intended use case is to be able to decode two different users for the same row, one would have all its columns prefixed by otheruser_ for example and the other one would have no prefix or "" as prefix.
In the decoder for the final type, I would then be able to decode both users as follow:
decoder = do
userA <- decoderUser @""
userB <- decoderUser @"otheruser_"
pure $ MyFinalType userA userB