What I am trying to do?
I am receing a JSON payload in IHP and would like to convert to record type.
What I have
Record type that I've generated with the IHP generators
data Resource' userId providerId bookings = Resource
{ id :: (Id' "resources")
, createdAt :: UTCTime
, updatedAt :: UTCTime
, userId :: userId
, providerId :: providerId
, name :: Text
, bookings :: bookings
, meta :: MetaBag
} deriving (Eq, Show)
type Resource = Resource' (Id' "users") (Id' "providers")(QueryBuilder.QueryBuilder "bookings")
I wasn't able to directly convert the json payload to Record
and therefore creating another temporary record to fetch values from json.
data ResourceCreateRequest = ResourceCreateRequest { name :: String }
instance FromJSON ResourceCreateRequest where
parseJSON = withObject "Resource" $ \o -> ResourceCreateRequest <$> o .: "name"
JSON payload
{"name": "X"}
My idea was to use temp record to replace just few specific fields in IHP's generated newRecord @Resource
. To show the results I am using (or trying to) in the controller
-- JRCR is a qualified name of the module with my temporary record
"application/json" -> renderJson (newRecord @Resource){ name = (JRCR.name getRequest) }
Question
Apparently I am having issues on Value
-> Resource
or Value
-> ResourceCreateRequest
conversion and cannot get it done correctly. Can you please help me out?
Current error
Record update is ambiguous, and requires a type signature
* In the second argument of `($)', namely
`(newRecord @Resource) {name = (JRCR.name getRequest)}'
In the expression:
renderJson $ (newRecord @Resource) {name = (JRCR.name getRequest)}
In a case alternative:
"application/json"
-> renderJson
$ (newRecord @Resource) {name = (JRCR.name getRequest)}
|
52 | "application/json" -> renderJson $ (newRecord @Resource){ name = (JRCR.name getRequest) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
CodePudding user response:
The problem is that type inference and DuplicateRecordFields
don't work well together. Here's a minimal program that demonstrates the same problem you're having, but without involving IHP or any other third-party code:
{-# LANGUAGE DuplicateRecordFields, TypeApplications #-}
data Foo = Foo { name :: String } deriving Show
data Bar = Bar { name :: String } deriving Show
class Baz a where
baz :: a
instance Baz Foo where
baz = Foo ""
instance Baz Bar where
baz = Bar ""
main :: IO ()
main = print $ (baz @Foo){ name = "qux" }
The solution here is to change baz @Foo
to baz @Foo :: Foo
. In this case, just baz :: Foo
would work too.
Similarly, changing newRecord @Resource
to newRecord @Resource :: Resource
, or maybe newRecord :: Resource
, should fix your code.