How do I route routes (using `~`) that are the result of functions?

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 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 this way:

scala> lazy val composite: Route = path("foo"){ r1(1) } ~ path("bar"){ r2(1) }
composite: akka.http.scaladsl.server.Route = <lazy>

      

I would like to use function composition along with chaining ~

. That is, I would like this to just work:

scala> lazy val composite: Int => Route = path("foo")(r1) ~ path("bar")(r2)

      

Except this is not: - (

<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 dot composition of functions. As Ramon shows below, this is easy to do if you want to duplicate a function app (which is what I want to avoid). I.e:

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 as good as it goes, but the implicit ConjunctionMagnet.fromRouteGenerator

in akka.http.scaladsl.server

gives me reason to think it's possible in akka-http directly

+3


source to share


1 answer


As the equivalent of the skalaz example you provided:

lazy val composite: Int => Route = 
  (i) => path("foo")(r1(i)) ~ path("bar")(r2(i))

      



Similarly, you can anonymize the parameter name, but this will result in two parameters:

lazy val composite: (Int,Int) => Route = path("foo")(r1(_)) ~ path("bar")(r2(_))

      

+1


source







All Articles