I have a post that has an Include' as I've fetched it with a fetchRelated, so it has this type:
post :: Include' ["comments"] Post
If I'd like to save it, I'd get an error
post
|> set #title "Foo"
|> updateRecord
The compiler will complain it's not a Post. It's an Include ... Post
My question is - can the Post be extracted out of the include, so I won't have to fetch it again from the DB?
There's no built-in function in IHP to do this. But you can use a custom helper like this:
And then use it like this:
Things can get slightly more complex when we have multiple Include. The compiler will error out,
We need to split this into multiple functions, each with types annotations:
March has explained the reason:
TL;DR:
updateFieldhas a more open type signature thansetand sometimes GHC needs a bit of helpIn very early IHP versions
updateFieldwas actuallysetand it was later changed (because it was causing errors like these). The core problem withupdateFieldis, that it's type definition is very open. It's defined asupdateField :: value' -> model -> model'. Heremodelandmodel'are two independent type variables. This means a call toupdateFieldcan actually change the return type of the record (e.g. turningPosttoPost "tags" LandingPage). The problem with your first version was that GHC could not figure out themodel'variable because multipleupdateFieldwere chained (themodeltype argument is easy for GHC to figure out, it's just that themodel'is independent of that).For comparison
setis defined asset :: value -> model -> model. In that case when GHC can figure outmodelit will never error. Sosetis typically easy to figure out and unlikely to error. One the other side the problem withsetis that it's less flexible and cannot change the output type (e.g. withmodel = Postit will beset :: value -> Post -> Post, so there's no way to express e.g. theIncludestuff). That's whyupdateFieldexists.