密封特征层次结构的Akka Http提取器指令

时间:2016-09-27 18:43:33

标签: scala akka-http

看起来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[_]?这样,我至少可以与&结合使用,而且我只需要模式匹配。

1 个答案:

答案 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部分,我将编辑以添加它们)