Как требовать во время компиляции, чтобы параметр типа был признаком (а не значением класса или другого типа)? - PullRequest
4 голосов
/ 26 мая 2019

Я ищу какую-то верхнюю границу для общего параметра T, который гарантирует, что T является признаком.

class Foo
trait Bar

def f[A ??? IsATrait] = ???

// f[Foo] Won't compile
f[Bar] // this is fine

Ответы [ 2 ]

11 голосов
/ 26 мая 2019

Попробуйте

typeOf[Bar].typeSymbol.asClass.isTrait // true
typeOf[Foo].typeSymbol.asClass.isTrait // false

Во время компиляции

import scala.language.experimental.macros
import scala.reflect.macros.whitebox

trait IsATrait[A]

object IsATrait { 
  implicit def materialize[A]: IsATrait[A] = macro impl[A]

  def impl[A: c.WeakTypeTag](c: whitebox.Context): c.Tree = {
    import c.universe._
    val tpA = weakTypeOf[A]
    if (tpA.typeSymbol.asClass.isTrait)
      q"new IsATrait[$tpA] {}"
    else c.abort(c.enclosingPosition, s"$tpA is not a trait")
  }
}

def f[A: IsATrait] = ???

f[Bar] // compiles

f[Foo]
//Information: IsATrait.materialize is not a valid implicit value for IsATrait[Foo] because:
//             hasMatchingSymbol reported error: Foo is not a trait
//
//Error: could not find implicit value for evidence parameter of type IsATrait[Foo]
//
//Error: not enough arguments for method f: (implicit evidence$1: IsATrait[Foo])Nothing.
//       Unspecified value parameter evidence$1.
0 голосов
/ 26 мая 2019

Можно ли требовать во время компиляции, чтобы параметр типа был признаком (а не значением класса или другого типа)?

номер

...