You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Motivation: I'm having to deal with Tapir, using it to generate client and service implementations for some APIs. I end up with values like these:
// Pure specification for an endpoint, used by the client and the servervalfooEndpoint:Endpoint[(AuthToken, FooInput), ApiError, FooOutput, Any]
// Complementary server-side implementation, without authentication.valfooImpl: (AuthedClient, FooInput) =>IO[Either[ApiError, FooOutput]]
// Endpoint + implementationvalfooServerEndpoint:ServerEndpoint[(AuthToken, FooInput), ApiError, FooOutput, Any, IO]
// Authentication, common for all endpointsvalauthenticate:AuthToken=>IO[Either[ApiError, AuthedClient]]
If you squint hard enough (and if you have enough endpoints to generalize), you can see that the three foo* values belong in three variants of the same shape that describes the API as a whole:
traitApi[F[_, _]] {
deffoo:F[FooInput, FooOutput]
// more endpoints here
}
typeEndpoint0[A, B] =Endpoint[(AuthToken, A), ApiError, B, Any]
typePureApi=Api[Endpoint0]
typeImpl[A, B] = (AuthedClient, A) =>IO[Either[ApiError, B]]
typeImplApi=Api[Impl]
typeServerEndpoint0[F[_], A, B] =ServerEndpoint[(AuthToken, A), ApiError, B, Any, F]
typeServerApi[F[_]] =Api[ServerEndpoint0[F, *, *]]
Authentication could be factored out if only Api had a version of mapK dealing with bifunctors (bimapK?). In the same vein, combining fooEndpoints and fooImpls is pure boilerplate, and could be implemented using something similar to map2K (bimap2K?).
Similar abstractions for trifunctors might also be useful, in case error types differ between endpoints.
The text was updated successfully, but these errors were encountered:
I think this would only work if we have a different form of natural transformation.
Instead of type ~>[F[_], G[_]] = arrow.FunctionK[F, G] it would have to be Function2K[F[_, _], G[_, _]] 🤔
Now that Scala 3 support is shaping up, we can add this with polymorphic functions.
But we need to first figure out how to add versions of the existing methods.
Motivation: I'm having to deal with Tapir, using it to generate client and service implementations for some APIs. I end up with values like these:
If you squint hard enough (and if you have enough endpoints to generalize), you can see that the three
foo*
values belong in three variants of the same shape that describes the API as a whole:Authentication could be factored out if only
Api
had a version ofmapK
dealing with bifunctors (bimapK
?). In the same vein, combiningfooEndpoint
s andfooImpl
s is pure boilerplate, and could be implemented using something similar tomap2K
(bimap2K
?).Similar abstractions for trifunctors might also be useful, in case error types differ between endpoints.
The text was updated successfully, but these errors were encountered: