在akka http路由列表上调用reduce会产生编译错误(参数连接没有隐式值)

eva*_*dor 5 functional-programming scala implicit akka akka-http

鉴于以下路线

val route1: PathMatcher[Unit] = PathMatcher("app")
val route2: PathMatcher1[String] = PathMatchers.Segment
val route3: PathMatcher[Unit] = PathMatcher("lastSegment")
Run Code Online (Sandbox Code Playgroud)

我可以轻松定义

val resultingRoute: PathMatcher[Tuple1[String]] = route1 / route2 / route3
Run Code Online (Sandbox Code Playgroud)

获得预期的类型(PathMatcher [Tuple [String]]).

但是以编程方式创建路线

val routeDef = List(route1, route2, route3)
val resultingRoute = routeDef.reduce((a,b) => a / b)
Run Code Online (Sandbox Code Playgroud)

不会编译,给我

找不到参数连接的隐含值:akka.http.scaladsl.server.util.TupleOps.Join [_1,_1]

此外,推断出的resultRoute类型是

PathMatcher[_ >: Unit with Tuple1[String] with join.Out]
Run Code Online (Sandbox Code Playgroud)

我真的很感激有任何提示给我一些迹象,说明我在这里做错了什么,或者如何解决这个问题.

为了完整性,这是我的导入:

import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{PathMatcher, _}
Run Code Online (Sandbox Code Playgroud)

非常感谢!

Fed*_*tta 1

您的问题是您的routeDef列表实际上是异构的,编译器推断其类型为List[PathMatcher[_ >: Tuple1[String] with Unit]].

鉴于此,该(a: PathMatcher[L])./(b: PathMatcher[R])方法隐式需要TupleOps.Join[L, R]akka.http.scaladsl.server.PathMatcherPathMatcher它不能从列表中的 s 类型推断出来routeDef


如果您愿意使用,shapeless则可以轻松地处理异构列表(HList在本上下文中称为 s):

import shapeless._
Run Code Online (Sandbox Code Playgroud)
val routeDef = route1 :: route2 :: route3 :: HNil
Run Code Online (Sandbox Code Playgroud)
object join extends Poly {
  implicit def casePathMatcher[A, B](
    implicit t: akka.http.scaladsl.server.util.TupleOps.Join[A,B]
  ) = use((a: PathMatcher[A], b: PathMatcher[B]) => a/b)
}
Run Code Online (Sandbox Code Playgroud)
object join extends Poly {
  implicit def casePathMatcher[A, B](
    implicit t: akka.http.scaladsl.server.util.TupleOps.Join[A,B]
  ) = use((a: PathMatcher[A], b: PathMatcher[B]) => a/b)
}
Run Code Online (Sandbox Code Playgroud)