-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
instance FromRow a => FromRow (Maybe a) #83
Comments
If you select only one column, use |
The Does my question make sense? Here's some example code data LeftEntity = LeftEntity
{ leId :: Id LeftEntity
, leName :: Text
, leAssociatedRightEntityId :: Id RightEntity
}
deriving (Show, Generic, ToRow, FromRow)
data RightEntity = RightEntity
{ reId :: Id RightEntity
, reName :: Text
, reDescription :: Text
}
deriving (Show, Generic, ToRow, FromRow)
getLeftEntityWithAssociatedRightEntity = do
rows :: [ LeftEntity :. Maybe RightEntity ] <- runSelect [PGQ.sqlExp|
select
le.id,
le.name,
le.associated_right_entity_id,
re.id,
re.name,
re.uuid
from left_entity le
left join right_entity re on re.id = le.associated_right_entity_id
|]
pure $
flip fmap rows $ \(leftEntity :. mRightEntity) ->
(leftEntity, mRightEntity)
This doesn't compile because there's no instance of So I have to change data RightEntityFields = RightEntityFields
{ reId :: Maybe (Id RightEntity)
, reName :: Maybe Text
, reDescription :: Maybe Text
}
deriving (Show, Generic, ToRow, FromRow) And then make a function I'm wanting to know if there's a way to avoid all that boilerplate. |
I see there's something close to what I want but it's for tuples: (FromField a, FromField b) => FromRow (Maybe (a, b)) Someone pointed out to me that I could try uncurrying the constructor I was wanting to parse into and map that over the So I could do something like getLeftEntitiesWithAssociatedRightEntities = do
rows :: [ LeftEntity :. Maybe RightEntity ] <-
List.map go <$> runSelect [PGQ.sqlExp|
select
le.id,
le.name,
le.associated_right_entity_id,
re.id,
re.name,
re.uuid
from left_entity le
left join right_entity re on re.id = le.associated_right_entity_id
|]
pure $
flip fmap rows $ \(leftEntity :. mRightEntity) ->
(leftEntity, mRightEntity)
where
go (left :. maybeRight) = left :. fmap (uncurry3 RightEntity) maybeRight That does seem to work and I like that much better than having to define an ad-hoc type to collect intermediate results. But I still wish I could just parse directly into |
There is nothing wrong in defining ad-hoc types for specific purposes. Types are cheap. Now as I think of it, the |
(FromField a, FromField b) => FromRow (Maybe (a, b)) That's different. It has |
If you enable FlexibleInstances, you can define a Maybe instance for your type. Still a bit of boilerplate, but at least you don't need an intermediate type. instance FromRow (Maybe RightEntity) where
fromRow = maybeRightEntity <$> field <*> field <*> field
maybeRightEntity :: Maybe (Id RightEntity) -> Maybe Text -> Maybe Text -> Maybe RightEntity
maybeRightEntity (Just a) (Just b) (Just c) = Just $ RightEntity a b c
maybeRightEntity = Nothing |
I'm kind of new to haskell, so forgive me if the answer to this is obvious, but I was attempting to do a left join in order to get
rows :: [LeftEntity :. Maybe RightEntity]
but then was informed by the compiler that there's no instance forinstance FromRow a => FromRow (Maybe a)
. So I ended up having parse into an intermediate structure first like[LeftEntity :. IntermediateRightEntityResults]
and then transformIntermediateRightEntityResult
intoMaybe RightEntity
. I would really prefer to be able to parse directly into the Maybe, though. Is there reason there isn't an instance forFromRow (Maybe a)
? And is there perhaps some other way to do what I want? Or is parsing into a temporary intermediate structure just how things are supposed to be done?The text was updated successfully, but these errors were encountered: