Using servant, I've got a type like the following, but more complex:
type MyAPI endpointTail result = "blah" :> Capture "a" A :> endpointTail :> Get '[JSON] result
Which means I can do things like this:
MyAPI "hello" HelloT
but when I do:
MyAPI "hello/world" HelloWorldT
Servant silently fails to produce my endpoint correctly, presumably because it doesn't expect a literal slash
When I try:
MyAPI ("hello" :> "world") HelloWorldT
I get a type error because :> is only defined when the right argument is of kind *, which "world" is not, it's of kind Symbol.
It seems for servant to work correctly, the :> has to be applied in a right associative fashion, one can't just add brackets willy nilly. So what I think I need is something like this:
type MyAPIF endpointTailF result = "blah" :> Capture "a" A :> endpointTail (Get '[JSON] result)
Note endpointTail is now a type function, endpointTailF.
Then I could do
type Blah t = "hello" :> "world" :> t
MyAPIF Blah HelloWorldT
But now I've got the issue of the compiler saying it doesn't like Blah being partially applied.
So in summary, I've got a nice reusable type which I'd like to keep using, I'd just like to be able to pass more parameters. If these were values I'd be able to do this easily, by passing a function "continuation" style, but I'm not sure of the solution in the type world. Any ideas?
Your deductions are all correct. Unless you want to crawl down the rabbit hole that is singleton defunctionalization (the usual method for working with partially applied type functions), you'll want to avoid treating type functions as arguments. Use a plain data structure instead.
For example, if you write a type function that prefixes a type using a list of URL path segments:
and then incorporate a call to this function within your API:
then this lets you write:
Full code example: