如何在 Scala 中使用否定类型? [英] How can I have a negation type in Scala?

查看:48
本文介绍了如何在 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆