检查scala中的部分函数是否为未知类型的值定义



我有以下特征(获得排名2多态性点击)

type Id[A] = A
trait ~>[F[_], G[_]] {
def apply[A](a: F[A]): G[A]
def isDefinedAt[A](a: A): Boolean}

和将部分函数转换为该特征的函数:

implicit def pft[B: ClassTag](f: PartialFunction[B, B])= new (Id ~> Id) {
def apply[A](a: A): A = f(a.asInstanceOf[B]).asInstanceOf[A]
def isDefinedAt[A: ClassTag](a: A)(implicit ev2: ClassTag[A]) : Boolean = /*type check*/
               f.isDefinedAt(a.asInstanceOf[B]) }

我的问题是isDefinedAt方法。我必须在运行时检查A是否是B的实例。a.isInstanceOf[B]由于类型擦除而不能工作

我尝试使用TypeTag/ClassTag和B,工作得很好,但A的类型总是Any.

那么,我如何检查A是否是B的实例呢?

更新:我在这个代码中使用它:

  def map[A](f: Id ~> Id, x: A): A =
    {
      val y = x match {
        //many matches more on my own data structures
        case l : List[_] => l.map(map(f,_))
        case m : Map[_,_] => m.map(map(f,_))
        case (a,b) => (map(f,a),map(f,b))
        case a => a
      }
      if (f.isDefinedAt(y))
        f(y).asInstanceOf[A]
      else
        y.asInstanceOf[A]
    }

如果我直接使用~>,一切都可以正常使用typeTag[A]。tpe & lt;: & lt;类型标签[B] .tpe。

但是如果我将它与这个映射函数typeTag[A]一起使用。

如果您同意修改isDefinedAt的签名以接受TypeTag,则可以这样实现pft:

  type Id[A] = A
  trait ~>[F[_], G[_]] {
    def apply[A](a: F[A]): G[A]
    def isDefinedAt[A: TypeTag](a: A): Boolean
  }
  implicit def pft[B: TypeTag](f: PartialFunction[B, B]) = new (Id ~> Id) {
    def apply[A](a: A): A = f(a.asInstanceOf[B]).asInstanceOf[A]
    def isDefinedAt[A: TypeTag](a: A): Boolean =
      typeTag[A].tpe =:= typeTag[B].tpe && f.isDefinedAt(a.asInstanceOf[B])
  }

此解决方案获得BA的TypeTag,并在委托给部分函数的isDefinedAt方法之前验证它们是相同类型。有关类型标签的更多信息,请参阅此回答。

例如:

val halfEven: PartialFunction[Int, Int] = {
  case n if n % 2 == 0 => n / 2
}
val halfEvenT: Id ~> Id = halfEven
halfEvenT.isDefinedAt(1) // false
halfEvenT.isDefinedAt(2) // true
halfEvenT.isDefinedAt("test") // false

更一般地说,您可以将受约束的部分转换定义为采用约束A的附加高级类型:

  trait ConstrainedPartialTransformation[F[_], G[_], C[_]] {
    def apply[A: C](a: F[A]): G[A]
    def isDefinedAt[A: C](a: A): Boolean
  }
  implicit def cpft[B: TypeTag](f: PartialFunction[B, B]) = new ConstrainedPartialTransformation[Id, Id, TypeTag] {
    def apply[A: TypeTag](a: A) = f(a.asInstanceOf[B]).asInstanceOf[A]
    def isDefinedAt[A: TypeTag](a: A) =
      typeTag[A].tpe =:= typeTag[B].tpe && f.isDefinedAt(a.asInstanceOf[B])
  }

这类似于Scalaz 7支持自然转换的方式,其中有一个上下文绑定在a上。

相关内容

  • 没有找到相关文章

最新更新