-
Notifications
You must be signed in to change notification settings - Fork 59
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
Mutually-recursive object types/schemas #33
Comments
I'll try to see if I can come up with a good solution for this issue -- in the short term you can use the following trick with type tweet = {
id : int;
replies : tweet list;
user: user;
} and user = {
username: string;
tweets: tweet list;
};
let rec tweet = lazy Schema.(obj
~name:"tweet"
~fields:(fun tweet -> [
field "id"
~typ:(non_null int)
~args:Arg.[]
~resolver:(fun ctx t -> t.id)
;
field "replies"
~typ:(non_null (list tweet))
~args:Arg.[]
~resolver:(fun ctx t -> t.replies)
;
field "user"
~typ:(non_null Lazy.(force user))
~args:Arg.[]
~resolver:(fun ctx t -> t.user)
]))
and user = lazy Schema.(obj
~name:"user"
~fields:(fun user -> [
field "username"
~typ:(non_null string)
~args:Arg.[]
~resolver:(fun ctx t -> t.id)
;
field "tweets"
~typ:(non_null (list (non_null Lazy.(force tweet))))
~args:Arg.[]
~resolver:(fun ctx t -> u.tweets)
])) |
Does the above work as a solution for now? |
It does, thank you!
…On Sun, Mar 12, 2017 at 11:43 AM, Andreas Garnaes ***@***.***> wrote:
Does the above work as a solution for now?
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#33 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AACJ4Mt7Pf2S0fhhgit0sa24thq1I8Lbks5rlDzWgaJpZM4MQo-1>
.
|
I have a branch locally which implements a fixpoint. It permits code like this: type foo = {
b : bar
}
and bar = {
f : foo
}
let foo, bar = Schema.(fix (fun factory ->
factory.obj "foo"
~fields:(fun (foo, bar) -> [
field "b"
~typ:bar
~args:Arg.[]
~resolve:(fun () f -> Some f.b)
]),
factory.obj "bar"
~fields:(fun (foo, bar) -> [
field "f"
~typ:foo
~args:Arg.[]
~resolve:(fun () b -> Some b.f)
])
)) So you get rid of type 'a factory = {
obj : 'ctx 'src. ?doc:string ->
string ->
fields:('a -> ('ctx, 'src) field list) ->
('ctx, 'src option) typ
}
val fix : ('a factory -> 'a) -> 'a Any thoughts on this API, @sgrove? (note that I'm not particularly fond of |
@andreas I'm not particular worries about how nice the API is right now (we can always refactor our client code later), but the biggest concern I have (that we're hitting in the real world right now) is circular deps, where one module can link into another (and vice-versa). I think this API would have the same problem. Would you recommend mutually recursive modules to get around this, or do you see a better/cleaner solution? |
I'm not sure I understand. Can you elaborate what you mean by circular deps with modules, perhaps with an example? |
Sure! So in file X I have a resolver which returns a But if file X has a resolver with a Imagine a |
It sounds to me like that problem is rooted in the requirement to have a non-cyclic dependency graph in OCaml. As such, it's hard to address in |
Thanks again for such a fun project to play with!
Related to #28, I've run into problems with mutually recursive types.
As a simplified example:
This will run into the same issues as #27,
Error: This kind of expression is not allowed as right-hand side of 'let rec'
This is actually a common pattern with Relay/Apollo clients, where relationships have
edges
fields, and each inside that is anode
field that in this case would be the actual tweet. The intermediate fields allow for e.g. cursors, total-count, etc. to describe the collection rather than the specific node.The text was updated successfully, but these errors were encountered: