After playing with Roc platform system + .NET (PR merged to the examples repo \o/), I was thinking about how I could implement some sort of type based web api platform that I always wanted to but never figured how to do it with C# or F# due to their lack of type inference.
My goal is to achieve the following syntax or similar:
main = \routes ->
routes
|> mapGet "/"
|> accepting (intParam "id" |> fromRoute)
|> producing3 (Ok Todo) BadRequest NotFound
|> usingHandler getTodos
essentially, this would enforce getTodos
to have the following signature:
getTodos : int -> [Ok Todo, BadRequest, NotFound]
This would make documenting the API much simpler with maybe a call like:
...
routes
|> mapGet "/"
...
|> usingHandler getTodos
|> usingOpenApi
With the |> usingOpenApi
line, the user would have open api (swagger) ready to go. But to do so, I would need to read the [Ok Todo, BadRequest, NotFound]
type and convert it to some sort of "schema" that I would transform into a OpenApi specification or anything similar.
My question is: Can I read roc types like values or maybe use a different approach to achieve the above behavior?
I think you can achieve the desired functionality with abilities, that would allow you to define custom types that have for example a function toSchema
.
hey @Anton I just had time to take a look at it now.
I'm not sure I understand the use of abilities in this scenario.
Do you mean that the Custom time (in the last example Todo
) would have to implement this custom ability with a toSchema
function? I didn't want the user to have to define any code besides the actual type.
My inspiration came from Haskell Servant, where I can define an API as a type. The only difference here would be that I would define an API with functions.
So, how could I convert a type such as Todo : { description: Str, done: Bool }
to, lets say, a json value like
{ "type": {"name": "Todo", "fields": [{"name": "description", "type": "string"}, {"name": "done", "type": "boolean"}]} }
Encode with either a custom encoder or the community made Jason encoder should work.
Oh, though you want type info, not to encode the actual value. That would definitely be a custom encoder.
Yeah, type info, not the actual value.
Ok, I'm gonna take a look at how encoders work, but I presume these are implemented in the platform somehow?
No, in roc. https://www.roc-lang.org/builtins/Encode#Encoder
Basically the encoder formatting function names give you the type info, so you could ignore the value and just encode type info. For structs still need to use it recursively, but that is no big deal.
Oh, I guess if you want the most type info, inspect may technically be better it also knows about sets and dictionaries. We probably should expand encode to know about these types as well, but it doesn't currently.
Example implementation in Inspect.roc for inspect (towards bottom of file) and TotallyNotJson.roc for encode. Just search for the files in the repo.
Mmmm, inspect sounds and looks like what I want... I'm taking a look at it. Thx @Brendan Hansknecht !
Ok, I think I finally understood. It took me a while to understand how abilities work. Probably because I kept imagining them being implemented on the platform and/or the base roc rust compiler code. There are still some things I can’t fully understand but I’ll give it a try. It compiles in my head xD
Last updated: Jul 05 2025 at 12:14 UTC