看起来Akka Http非常接近于允许您根据case class
的{{3}}来定义ADT的提取器。我曾尝试为sealed trait
层次结构编写一个提取器,但由于Directive
的不变性,它似乎无法工作:
scala> :paste
// Entering paste mode (ctrl-D to finish)
import akka.http.scaladsl.server.Directives._
sealed trait QueryStringOption
case object NoOption extends QueryStringOption
case class OptionA(value: Int) extends QueryStringOption
case class OptionB(value: String) extends QueryStringOption
val noOptionExtractor = provide(NoOption)
val optionAExtractor = parameter('optionA.as[Int]).as(OptionA)
val optionBExtractor = parameter('optionB.as[String]).as(OptionB)
val queryStringOptionExtractor = optionAExtractor | optionBExtractor | noOptionExtractor
// Exiting paste mode, now interpreting.
<console>:51: error: type mismatch;
found : akka.http.scaladsl.server.Directive1[OptionB]
(which expands to) akka.http.scaladsl.server.Directive[(OptionB,)]
required: akka.http.scaladsl.server.Directive[(Product with Serializable with QueryStringOption,)]
Note: (OptionB,) <: (Product with Serializable with QueryStringOption,), but class Directive is invariant in type L.
You may wish to define L as +L instead. (SLS 4.5)
val queryStringOptionExtractor = optionAExtractor | optionBExtractor | noOptionExtractor
^
这里有更好的解决方案吗?
是否有办法将我的提取器提升到Option[_]
?这样,我至少可以与&
结合使用,而且我只需要模式匹配。
答案 0 :(得分:0)
您只需要添加类型,以便指令具有正确的类型:
import akka.http.scaladsl.server.Directive1
import akka.http.scaladsl.server.Directives._
sealed trait QueryStringOption
case object NoOption extends QueryStringOption
case class OptionA(value: Int) extends QueryStringOption
case class OptionB(value: String) extends QueryStringOption
val noOptionExtractor: Directive1[QueryStringOption] = provide(NoOption)
val optionAExtractor: Directive1[QueryStringOption] = parameter('optionA.as[Int]).as(OptionA)
val optionBExtractor: Directive1[QueryStringOption] = parameter('optionB.as[String]).as(OptionB)
// should now compile as all alternatives now have the same type
val queryStringOptionExtractor = optionAExtractor | optionBExtractor | noOptionExtractor
(此示例还缺少extends QueryStringOption
部分,我将编辑以添加它们)