Skip to content

Implement default input values #73

@teh

Description

@teh

default values are used for input arguments, e.g. type Greet { say(word: String = "hello"): String }

This poses a problem for us because the API is specified as a type, and Haskell does not support encoding terms as types in a straight-forward manner, so we can't make the default value part of the type signature.

We do however need to be able to access defaults independently of running a query for features such as introspection, and validation (input type coercion).

What we can do instead is use a unique type (e.g. newtypeing) and a class instance to return the default value, thus mapping from the type world to the value world, and allowing a type in the signature.

This can be done on a per-type level, e.g.

type Query = Object "Query" '[]
  '[ Argument "age" NewtypedInt :> Field "root" Text ]
instance Defaultable NewtypedInt where defaultFor _ = Just 33

or we could use Symbol kinds to look up defaults. This could be slightly more fragile due to colliding instances, e.g.

type Query = Object "Query" '[]
  '[ ArgumentWithDefault "age" Int "defaultAge" :> Field "root" Text ]
instance Defaultable "defaultAge" where defaultFor = Just 33

The solution above could be made slightly safer by using the whole argument as the instance class variable, though this too can suffer from accidental collisions in large APIs. There may be a unique type combination for indexing but it's not immediately obvious what that would be. Example:

instance Defaultable (Argument "age" Int) where defaultFor = Just 33

An alternative is to have a handler to handle requests, and a parallel handler to return defaults where required. E.g.

buildResolver @Query queryHandler defaultHandler

IMO that imposes a lot of work for handlers that don't have defaults (which seems to be most of them AFAICT).

The solutions so far are all conforming to the spec. We could also compromise conformance and decide to e.g. validate default arguments only in query resolution, and to not export them for introspection.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions