scala> import akka.http.scaladsl.server._; import Directives._
import akka.http.scaladsl.server._
import Directives._
Suppose I have two functions from some type (Int
, say) to a Route
:
scala> lazy val r1: Int => Route = ???
r1: Int => akka.http.scaladsl.server.Route = <lazy>
scala> lazy val r2: Int => Route = ???
r2: Int => akka.http.scaladsl.server.Route = <lazy>
I can compose a route thusly:
scala> lazy val composite: Route = path("foo"){ r1(1) } ~ path("bar"){ r2(1) }
composite: akka.http.scaladsl.server.Route = <lazy>
What I would like to do is use function composition together with the ~
path chaining. That is, I'd love for this to just work:
scala> lazy val composite: Int => Route = path("foo")(r1) ~ path("bar")(r2)
Except it doesn't :-(
<console>:31: error: type mismatch;
found : Int => akka.http.scaladsl.server.Route
(which expands to) Int => (akka.http.scaladsl.server.RequestContext => scala.concurrent.Future[akka.http.scaladsl.server.RouteResult])
required: akka.http.scaladsl.server.Route
(which expands to) akka.http.scaladsl.server.RequestContext => scala.concurrent.Future[akka.http.scaladsl.server.RouteResult]
lazy val composite: Int => Route = path("foo")(r1) ~ path("bar")(r2)
^
EDIT
I am trying to do this using point-free function composition,. As Ramon's answer below demonstrates, it's easy to do this if you are willing to duplicate the function application (but this is what I want to avoid). That is:
lazy val composite: Int => Route
= i => path("foo")(r1(i)) ~ path("bar")(r2(i))
NOTE
Using scalaz, I can do this:
scala> import akka.http.scaladsl.server._; import Directives._; import scalaz.syntax.monad._; import scalaz.std.function._
import akka.http.scaladsl.server._
import Directives._
import scalaz.syntax.monad._
import scalaz.std.function._
scala> lazy val r1: Int => Route = ???
r1: Int => akka.http.scaladsl.server.Route = <lazy>
scala> lazy val r2: Int => Route = ???
r2: Int => akka.http.scaladsl.server.Route = <lazy>
scala> lazy val composite = for (x <- r1; y <- r2) yield path("foo")(x) ~ path("bar")(y)
composite: Int => akka.http.scaladsl.server.Route = <lazy>
Which is so good as it goes but the implicit ConjunctionMagnet.fromRouteGenerator
in akka.http.scaladsl.server
gives me cause to think it might be possible in akka-http directly
The equivalent to the scalaz example you gave is:
Similarly, you could anonymize the parameter name but that would result in 2 parameters: