Support F# list type conversion
Is your feature request related to a problem?
I have been writing an F# wrapper for HotChocolate. It has been going pretty well but I recently ran into an issue when trying to read an argument that is type list. This issue is reproducible with the following query definition, written in F#:
type QueryObject() =
inherit ObjectType<obj>()
with
override self.Configure(descriptor: IObjectTypeDescriptor<obj>) =
descriptor.Field("testField")
.Argument("testArg", fun a -> a.Type<ListType<StringType>>() |> ignore)
.Resolve<list<string>>(fun (context: IResolverContext) -> context.ArgumentValue<list<string>>("testArg"))
.Type<ListType<StringType>>()
|> ignore
This produces the following runtime error when attempting to query the field:
System.NotSupportedException: Unable to convert type from `List`1` to `FSharpList`1`
at HotChocolate.Utilities.DefaultTypeConverter.Convert(Type from, Type to, Object source)
at HotChocolate.Utilities.DictionaryToObjectConverter.VisitList(IReadOnlyList`1 list, ConverterContext context)
at HotChocolate.Utilities.DictionaryVisitor`1.Visit(Object value, TContext context)
at HotChocolate.Utilities.DictionaryToObjectConverter.Convert(Object from, Type to)
at HotChocolate.Types.InputParser.ConvertValue(Type requestedType, Object value)
at HotChocolate.Types.InputParser.ParseLiteral(IValueNode value, IInputFieldInfo field, Type targetType)
at HotChocolate.Execution.Processing.MiddlewareContext.CoerceArgumentValue[T](ArgumentValue argument)
at HotChocolate.Execution.Processing.MiddlewareContext.ArgumentValue[T](NameString name)
at Schema.Pipe #2 input at line [email protected](IResolverContext context)
It is possible to write a custom type converter:
let configureServices (services: IServiceCollection) =
services.AddGraphQLServer()
.ModifyRequestOptions(fun opt -> opt.IncludeExceptionDetails <- true)
.AddQueryType<QueryObject>()
.AddTypeConverter<System.Collections.Generic.List<string>, list<string>>(fun l -> List.ofSeq l)
.InitializeOnStartup()
|> ignore
But this would need to be done for each list type, which I haven't found a good way to generalize it for my wrapper.
The solution you'd like
Support for converting C# lists to F# lists. Thanks for your awesome program!
Product
Hot Chocolate
Lets create an f# package that handles it generically ... F# support is on our list but we are lacking people from the community that help us :)
Strange ... it implements IREadOnlyList which we should be able to handle ... let me check
Would you be willing to contribute some unit tests? This would help us make it better for F#
The issue is in the type conversion. You could fix it by providing a IChangeTypeProvider which we use to compile converters at runtime for generics. However, if you contribute a F# unit tests I will patch it for you in the core.
Hey Michael, thanks for the response!
I found out that FSharpList was not being converted because it doesn't implement a default constructor.
I put together some unit tests and my attempt at an IChangeTypeProvider on my fork:
https://github.com/Leaxe/hotchocolate/tree/fsharp-list-converters
This is my first time working with C# so let me know if it looks reasonable and if I should open a pull request. I am also interested in adding a converter for C# Nullable to F# Option.