如何在 Scala 中使用否定类型? [英] How can I have a negation type in Scala?
问题描述
我想做这样的事情:
def iDontLikeStrings(arg: Not[String]) = {....}
基本上,这应该可以编译:
Basically, this should compile:
iDontLikeStrings(23)
iDontLikeStrings(true)
这不应该编译:
iDontLikeStrings("hello")
推荐答案
这是我的实现(参见 gist):
Here is my implementation (see gist):
第 1 步:编码以捕获 A 不是 B 的子类型
Step 1: Encoding to capture A is not a subtype of B
trait NotSubTypeOf[A, B]
注意:我们可以用中缀表示法来写A NotSubTypeOf B
而不是NotSubTypeOf[A, B]
Note: We can use infix notation to write A NotSubTypeOf B
instead of NotSubTypeOf[A, B]
第 2 步:任意两种类型 A 和 B 的证据,A 不是 B 的子类型
Step 2: Evidence for any two arbitrary types A and B, A is not a subtype of B
implicit def isSub[A, B]: A NotSubTypeOf B = null
第 3 步:定义二义性隐式以在 A 是 B 的子类型(或 A =:= B)的情况下触发编译错误
Step 3: Define ambigious implicits to trigger compile error in case A is a subtype of B (or A =:= B)
implicit def iSubAmbig1[A, B >: A]: A NotSubTypeOf B = null
implicit def iSubAmbig2[A, B >: A]: A NotSubTypeOf B = null
第 4 步:定义 类型-lambda 表示否定类型:
Step 4: Define a type-lambda for the negation type:
type Not[T] = {
type L[U] = U NotSubTypeOf T
}
使用 kind-projector,这可以提高可读性.
With kind-projector, this can be made much more readable.
第 5 步:完成!
def iDontLikeStrings[A: Not[String]#L](a: A) = {
println(a)
}
iDontLikeStrings(23) // compiles
iDontLikeStrings(true) // compiles
//iDontLikeStrings("hello") // does not compile
最后一行的编译器错误信息可以在 Scala 2.12 中做得更好,它解决了 SI-6806.
The compiler error message for the last line can be made better in Scala 2.12 which addresses SI-6806.
此外,所有这些都内置在 Shapeless 中.
Also, all of this is built into Shapeless.
这篇关于如何在 Scala 中使用否定类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!