与具有类型参数的案例类的模式匹配不起作用

时间:2015-10-31 10:21:19

标签: scala

我在相应的伴随对象中有一些unapply的案例类,我将其用于模式匹配,如下所示:

trait DAO [T] {
  def create: Int
  def insert(model: List[T]): Int
  def update(id: String, name: String): Int
  def delete(id: String): Int
  def all: List[T]
  def find(id: String): List[T]
  def findSome(id: String): List[T]
}

sealed trait Service[A]
final case class Create[A](implicit val dao: DAO[A]) extends Service[Int]
final case class Insert[A](model: List[A], implicit val dao: DAO[A]) extends Service[Int]

object Create_{
  def unapply[A](in: Create [A])= Some(in.dao)
}
object Insert_ {
  def unapply[A](in: Insert[A]) = Some((in.model,in.dao))
}

case class F(id:String)

implicit val abc = new DAO[F] {
  def create = 1
  def insert(model: List[F]) = 1
  def update(id: String, name: String) = 1
  def delete(id: String) = c1
  def all = List(F("Test"))
  def find(id: String) = List(F("Test"))
  def findSome(id: String) = List(F("Test"))
   }

def b[A](in: Service[A]) = {
  in match {
    case Create_(dao) => dao.create
    case Insert_(model, dao) => dao.insert(model)
  }
}

当我加载上述文件时,REPL会抱怨以下错误:

scala> :load ..../tools/scala/macros/test.scala
Loading ...../tools/scala/macros/test.scala...
defined trait DAO
defined trait Service
defined class Create
defined class Insert
defined class F
defined object Create_
defined object Insert_
abc: DAO[F] = $anon$1@3e776a48
<console>:65: error: type mismatch;
found   : List[Any]
required: List[A] where type +A
case  Insert_(model, dao) => dao.insert(model)

它没有编译。

3 个答案:

答案 0 :(得分:1)

问题在于:

Insert[+A,B](model: List[A], implicit val dao:DAO[B])

您允许模型和DAO的列表元素使用不同的类型,但DAO只需要一种类型:

  def insert(model:List[T]):Int

您可以通过要求插入类型相同来解决此问题。然后保证您为DAO传递正确的模型类型。

Insert[A](model: List[A], implicit val dao:DAO[A])

答案 1 :(得分:1)

剩下的问题是case class Create[A](implicit val dao: DAO[A])case class Create[A]()(implicit val dao: DAO[A])相同。因此case Create(dao)是非法的,而是case Create()。使用case Create_(dao)或从implicit val类定义中删除Create

答案 2 :(得分:0)

解决方案是

 def b[A](in: Service[A]) = {
  in match {
    case Create_(dao) => dao.create
    case Insert_(model:List[A], dao:DAO[A]) => dao.insert(model)
 }

还有警告!!!

 scala> :load .../tools/scala/macros/Test.scala
 Loading .../tools/scala/macros/Test.scala...
 defined trait DAO
import scalaz.{Free, $tilde$greater, Id, Coyoneda}
defined trait Service
defined trait Command
defined type alias Functor
defined class Create
defined class Insert
defined class Execute
defined class F
defined object Create_
defined object Insert_
defined object Execute_
lift: [A](service: Service[A])scalaz.Free[Functor,A]
abc: DAO[F] = $anon$1@2a071108
<console>:219: warning: abstract type pattern A is unchecked since it is   eliminated by erasure
            case  Insert_(model:List[A], dao:DAO[A]) => dao.insert(model)
                                ^
 <console>:219: warning: abstract type A in type pattern DAO[A] is unchecked since it is eliminated by erasure
            case  Insert_(model:List[A], dao:DAO[A]) => dao.insert(model)
                                       ^
<console>:217: warning: match may not be exhaustive.
It would fail on the following input: Insert(_, _)
          in match {
             ^
 b: [A](in: Service[A])Int