Scala 中如何拥有否定类型?

问题描述 投票:0回答:2

我想做这样的事情:

def iDontLikeStrings(arg: Not[String]) = {....}

基本上,这应该编译:

iDontLikeStrings(23) 
iDontLikeStrings(true)

这不应该编译:

iDontLikeStrings("hello") 
scala type-systems
2个回答
6
投票

这是我的实现(参见要点):

第1步:编码捕获A不是B的子类型

trait NotSubTypeOf[A, B] 

注意:我们可以使用中缀表示法来写

A NotSubTypeOf B
而不是
NotSubTypeOf[A, B]

第2步:任意两个类型A和B的证据,A不是B的子类型

implicit def isSub[A, B]: A NotSubTypeOf B = null

第 3 步:定义模糊隐式以在 A 是 B 的子类型(或 A =:= B)的情况下触发编译错误

implicit def iSubAmbig1[A, B >: A]: A NotSubTypeOf B = null
implicit def iSubAmbig2[A, B >: A]: A NotSubTypeOf B = null

第 4 步:为否定类型定义 type-lambda

type Not[T] = {
  type L[U] = U NotSubTypeOf T
}

使用 kind-projector,这可以变得更具可读性。

第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

此外,所有这些都内置于 Shapeless 中。


0
投票

在 scala 3 中这变得相当简单:

import scala.util.NotGiven

def iDontLikeStrings[T: [T] =>> NotGiven[T =:= String]](t: T) = {....}
© www.soinside.com 2019 - 2024. All rights reserved.