This meeting focused primarily around the idea of a ServiceDefinition. From a ServiceDefintion, the HTTP API can produce a running service, documentation and a client.
John referenced previous work, redeyes, which will be our starting point.
Below is the example from the redeyes README
import redeyes.api._
val request: Api[Int] =
GET >~>
path("/employees/") >~>
contentType("application/json") >~>
queryInt("limit")
val response: Api[Json] =
contentType("application/json") >~> content(JsonCodec)
val listEmployees = serviceM(request, response) { limit =>
loadAllEmployees(limit).toJson
}
val docs: Markdown = document(listEmployees)
val server: Task[Unit] = compileToServer(listEmployees)
val remoteService: Int => Task[Json] = remotely(listEmployees)("localhost", 80)
server.runThe ServiceDefinition has the following components:
request[A]: A definition of an HTTP endpoint, method, URL, headers, etc. WhereAis extracted from the request.response[B]: The result of arequest, and encoders specific toT.service: Monadic function whereA => M[B], such that a request providesAand the responseB. (For now avoid focusing onM, the key is providing a function that acceptsAand returnsB).- documentation: Can be produced from any
ServiceDefinition - "server": Produces a "runnable" HTTP service and a client.
John spent some time focused on going through his thinking on what is necessary to solve this problem and why other problems have failed in the past. I highly suggest reading through redeyes and the README is a great place to start.
Balance is crucial to this effort. Previous efforts with Parsers and Functions were unable to meet these goals. Functions and Parser both compose sufficiently well to build a ServiceDefinition but the semantics of that definition are lost and cannot be inspected. The inspection is necessary for documentation and client generation (key insight).
I think that John will be walking us through some more of the high level design work necessary to get the balance correct. I suspect that Applicative Functors will be very relevant to our project. These types will allow us to "inspect" any part of a ServiceDefinition and produce documentation and client in a type safe manner.