如何从 TypeClass 解析中排除特定类型?
How can I exclude a specific type from a TypeClass resolution?
我想为大多数类型提供 ToCondition
操作,但不为字符串提供。 (这是在移植 Javascript 代码时,非空和非零测试经常进行,重写所有此类测试以进行适当比较是乏味的)。这样做很容易,所以我收到错误运行时:
trait ToCondition[T] {
def apply(x: T): Boolean
}
implicit object ToConditionInt extends ToCondition[Int] {
override def apply(x: Int) = x != 0
}
implicit object ToConditionString extends ToCondition[String] {
override def apply(x: String) = throw new UnsupportedOperationException("Cannot use String as a condition")
}
implicit object ToConditionAnyRef extends ToCondition[AnyRef] {
override def apply(x: AnyRef) = x != null
}
def toCondition[T: ToCondition](a: T): Boolean = implicitly[ToCondition[T]].apply(a)
toCondition(1) // true
toCondition(null:AnyRef) // false
toCondition("") // throws runtime
能否以某种方式表达此约束,以便我在编译时得到错误?
如果你被允许使用 shapeless,那么使用类型不等式 =:!=
。这是 String
:
引发编译错误的版本
import shapeless._
trait ToCondition[T] {
def apply(x: T): Boolean
}
implicit object ToConditionInt extends ToCondition[Int] {
override def apply(x: Int) = x != 0
}
implicit object ToConditionString extends ToCondition[String] {
override def apply(x: String) = throw new UnsupportedOperationException("Cannot use String as a condition")
}
implicit object ToConditionAnyRef extends ToCondition[AnyRef] {
override def apply(x: AnyRef) = x != null
}
//Note the implicit value here
def toCondition[T: ToCondition](a: T)(implicit ev: T =:!= String) : Boolean = implicitly[ToCondition[T]].apply(a)
def main(args : Array[String]) {
toCondition(1) // true
toCondition(null:AnyRef) // false
toCondition("") // compile error
}
您可以将 广义类型约束 与条件一起使用,这永远不会为真,例如 String =:= Nothing
:
implicit def ToConditionString(implicit ev: String =:= Nothing) = new ToCondition[String] {
override def apply(x: String) = throw new UnsupportedOperationException("Cannot use String as a condition")
}
然后
toCondition("")
编译时失败:
could not find implicit value for evidence parameter of type ToCondition[String]
我想为大多数类型提供 ToCondition
操作,但不为字符串提供。 (这是在移植 Javascript 代码时,非空和非零测试经常进行,重写所有此类测试以进行适当比较是乏味的)。这样做很容易,所以我收到错误运行时:
trait ToCondition[T] {
def apply(x: T): Boolean
}
implicit object ToConditionInt extends ToCondition[Int] {
override def apply(x: Int) = x != 0
}
implicit object ToConditionString extends ToCondition[String] {
override def apply(x: String) = throw new UnsupportedOperationException("Cannot use String as a condition")
}
implicit object ToConditionAnyRef extends ToCondition[AnyRef] {
override def apply(x: AnyRef) = x != null
}
def toCondition[T: ToCondition](a: T): Boolean = implicitly[ToCondition[T]].apply(a)
toCondition(1) // true
toCondition(null:AnyRef) // false
toCondition("") // throws runtime
能否以某种方式表达此约束,以便我在编译时得到错误?
如果你被允许使用 shapeless,那么使用类型不等式 =:!=
。这是 String
:
import shapeless._
trait ToCondition[T] {
def apply(x: T): Boolean
}
implicit object ToConditionInt extends ToCondition[Int] {
override def apply(x: Int) = x != 0
}
implicit object ToConditionString extends ToCondition[String] {
override def apply(x: String) = throw new UnsupportedOperationException("Cannot use String as a condition")
}
implicit object ToConditionAnyRef extends ToCondition[AnyRef] {
override def apply(x: AnyRef) = x != null
}
//Note the implicit value here
def toCondition[T: ToCondition](a: T)(implicit ev: T =:!= String) : Boolean = implicitly[ToCondition[T]].apply(a)
def main(args : Array[String]) {
toCondition(1) // true
toCondition(null:AnyRef) // false
toCondition("") // compile error
}
您可以将 广义类型约束 与条件一起使用,这永远不会为真,例如 String =:= Nothing
:
implicit def ToConditionString(implicit ev: String =:= Nothing) = new ToCondition[String] {
override def apply(x: String) = throw new UnsupportedOperationException("Cannot use String as a condition")
}
然后
toCondition("")
编译时失败:
could not find implicit value for evidence parameter of type ToCondition[String]