在 akka http 路由列表上调用 reduce 会产生编译错误(参数连接没有隐式值)
calling reduce on list of akka http routes yields compilation error (no implicit value for parameter join)
给定以下路线
val route1: PathMatcher[Unit] = PathMatcher("app")
val route2: PathMatcher1[String] = PathMatchers.Segment
val route3: PathMatcher[Unit] = PathMatcher("lastSegment")
我可以轻松定义
val resultingRoute: PathMatcher[Tuple1[String]] = route1 / route2 / route3
获取预期类型 (PathMatcher[Tuple[String]])。
但是像
一样以编程方式创建路线
val routeDef = List(route1, route2, route3)
val resultingRoute = routeDef.reduce((a,b) => a / b)
不会编译,给我
could not find implicit value for parameter join: akka.http.scaladsl.server.util.TupleOps.Join[_1,_1]
此外,resultRoute的推断类型是
PathMatcher[_ >: Unit with Tuple1[String] with join.Out]
如果能给我一些提示,告诉我这里做错了什么或如何解决这个问题,我将不胜感激。
为了完整起见,这是我的导入:
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{PathMatcher, _}
非常感谢!
你的缩减表达式有几个问题。
1.减少 & 关联性
通过使用 reduce
,而不是 reduceLeft
或 reduceRight
,您是说
(a / b) / c === a / (b / c)
因为简单的 reduce 并不能确定排序。
我不认为路径匹配器组合是关联的。
2。减少 & 单位
使用 reduce 的另一个问题是它对于空列表是未定义的,因此结果总是不明确的。几乎总是更好的选择是 reduceOption
.
你的问题是你的 routeDef
列表实际上是异构的,编译器推断它的类型是 List[PathMatcher[_ >: Tuple1[String] with Unit]]
.
鉴于此,(a: PathMatcher[L])./(b: PathMatcher[R])
方法隐式需要一个 TupleOps.Join[L, R]
:akka.http.scaladsl.server.PathMatcher。它无法从您的 routeDef
列表中的 PathMatcher
s 类型推断出来。
如果您愿意使用 shapeless
,您就可以轻松地处理异构列表(在此上下文中称为 HList
s):
import shapeless._
val routeDef = route1 :: route2 :: route3 :: HNil
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)
}
val resultingRoute: PathMatcher[Tuple1[String]] = routeDef.reduceLeft(join)
给定以下路线
val route1: PathMatcher[Unit] = PathMatcher("app")
val route2: PathMatcher1[String] = PathMatchers.Segment
val route3: PathMatcher[Unit] = PathMatcher("lastSegment")
我可以轻松定义
val resultingRoute: PathMatcher[Tuple1[String]] = route1 / route2 / route3
获取预期类型 (PathMatcher[Tuple[String]])。
但是像
一样以编程方式创建路线val routeDef = List(route1, route2, route3)
val resultingRoute = routeDef.reduce((a,b) => a / b)
不会编译,给我
could not find implicit value for parameter join: akka.http.scaladsl.server.util.TupleOps.Join[_1,_1]
此外,resultRoute的推断类型是
PathMatcher[_ >: Unit with Tuple1[String] with join.Out]
如果能给我一些提示,告诉我这里做错了什么或如何解决这个问题,我将不胜感激。
为了完整起见,这是我的导入:
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{PathMatcher, _}
非常感谢!
你的缩减表达式有几个问题。
1.减少 & 关联性
通过使用 reduce
,而不是 reduceLeft
或 reduceRight
,您是说
(a / b) / c === a / (b / c)
因为简单的 reduce 并不能确定排序。
我不认为路径匹配器组合是关联的。
2。减少 & 单位
使用 reduce 的另一个问题是它对于空列表是未定义的,因此结果总是不明确的。几乎总是更好的选择是 reduceOption
.
你的问题是你的 routeDef
列表实际上是异构的,编译器推断它的类型是 List[PathMatcher[_ >: Tuple1[String] with Unit]]
.
鉴于此,(a: PathMatcher[L])./(b: PathMatcher[R])
方法隐式需要一个 TupleOps.Join[L, R]
:akka.http.scaladsl.server.PathMatcher。它无法从您的 routeDef
列表中的 PathMatcher
s 类型推断出来。
如果您愿意使用 shapeless
,您就可以轻松地处理异构列表(在此上下文中称为 HList
s):
import shapeless._
val routeDef = route1 :: route2 :: route3 :: HNil
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)
}
val resultingRoute: PathMatcher[Tuple1[String]] = routeDef.reduceLeft(join)