我在Scala中的函数返回超类型,而我的类型类无法处理它

时间:2019-10-18 12:46:04

标签: scala generics functional-programming typeclass implicit

我正在尝试实现功能,但是在解决现实世界中的问题时,我需要一些基础知识方面的帮助。我喜欢类型类的想法,并在将来添加更多隐式类型。

      trait Query {
       def queryDetails: QueryDetails
      }

      case class LocalQueryType(queryDetails: QueryDetails) extends Query
      case class JdbcQueryType(queryDetails: QueryDetails) extends Query

      def queryTypeFactory(queryDetails: QueryDetails): Query = {
         queryDetails.platform match {
            case c if queryDetails.platform.contains("-file://") => LocalQueryType(queryDetails)
            case _ => JdbcQueryType(queryDetails)
          }
      }

然后,我有一个用于查找本地或Jdbc类型的类型类,但是由于它仅接收查询类型,因此它不起作用。

我曾尝试使用如下通用名称:


     def queryTypeFactory[T<:Query](queryDetails: QueryDetails): T = {
         queryDetails.platform match {
            case c if queryDetails.platform.contains("-file://") => LocalQueryType(queryDetails)
            case _ => JdbcQueryType(queryDetails)
          }
     }

添加类型类别:


trait QueryTask[A] {
  def runQuery(a: A): String
}

object QueryTask {

    def apply[A](implicit sh: QueryTask[A]): QueryTask[A] = sh

    object ops {
      def runQuery[A: QueryTask](a: A) = QueryTask[A].runQuery(a)

      implicit class ShowOps[A: QueryTask](a: A) {
        def runQuery = QueryTask[A].runQuery(a)
      }
    }

    implicit val localQuery: QueryTask[LocalQueryType] =
      instance(localQueryType => s"running local: ${localQueryType.queryDetails.command} on platform: ${localQueryType.queryDetails.platform}")

    implicit val jdbcQuery: QueryTask[JdbcQueryType] =
      instance(jdbcQueryType => s"running jdbc: ${jdbcQueryType.queryDetails.command} on platform: ${jdbcQueryType.queryDetails.platform}")

  def instance[A](func: A => String): QueryTask[A] =
    new QueryTask[A] {
      def runQuery(a: A): String = func(a)
    }


想法是不要使用通常的OO工厂或策略模式。

1 个答案:

答案 0 :(得分:0)

类型类方法在您的用例中似乎不起作用。

隐式在编译时解决。因此,为了确定需要哪个实例,QueryTask[LocalQueryType]QueryTask[JdbcQueryType]编译器必须在编译时知道类型ALocalQueryType还是JdbcQueryType

但是似乎您是根据queryDetails.platform.contains("-file://")(即在运行时)来决定的。

似乎您需要常规的模式数学。您应该在必要时使用类型类模式。