gpt4 book ai didi

scala - 如何在 Scala 中正确使用模棱两可的隐式进行类型否定

转载 作者:行者123 更新时间:2023-12-01 13:13:18 26 4
gpt4 key购买 nike

最终我想要做的是为某些特定类型提供一个类型类的实现 T以及所有其他非 T 类型的实现.我认为(可能是错误的)最简单的方法是通过 this question 中描述的模棱两可的隐式尝试类型否定。 .但是,如果我不小心忽略了隐式类型类声明,我的代码仍然可以编译(应该吗?)但包含错误,因为只使用了一种实现。

这是定义上下文绑定(bind)的方式:

scala> trait NotAnInt[A]
defined trait NotAnInt

scala> implicit def everythingIsNotAnInt[A]: NotAnInt[A] = new NotAnInt[A] {}
everythingIsNotAnInt: [A]=> NotAnInt[A]

scala> implicit def intsAreInts1: NotAnInt[Int] = ???
intsAreInts1: NotAnInt[Int]

scala> implicit def intsAreInts2: NotAnInt[Int] = ???
intsAreInts2: NotAnInt[Int]

scala> implicit def nothingsAreInts1: NotAnInt[Nothing] = ???
nothingsAreInts1: NotAnInt[Nothing]

scala> implicit def nothingsAreInts2: NotAnInt[Nothing] = ???
nothingsAreInts2: NotAnInt[Nothing]

此时 NotAnInt[T] 对除 Int/Nothing 之外的所有 T 都是可召唤的:
scala> implicitly[NotAnInt[String]]
res3: NotAnInt[String] = $anon$1@1a24fe09

scala> implicitly[NotAnInt[Int]]
<console>:16: error: ambiguous implicit values:
both method intsAreInts1 of type => NotAnInt[Int]
and method intsAreInts2 of type => NotAnInt[Int]
match expected type NotAnInt[Int]
implicitly[NotAnInt[Int]]
^

scala> implicitly[NotAnInt[Nothing]]
<console>:18: error: ambiguous implicit values:
both method nothingsAreInts1 of type => NotAnInt[Nothing]
and method nothingsAreInts2 of type => NotAnInt[Nothing]
match expected type NotAnInt[Nothing]
implicitly[NotAnInt[Nothing]]
^

现在我有我的 NotAnInt定义了上下文绑定(bind)我可以使用它的实现创建我的类型类:
scala> trait IntChecker[A] { def isInt(): Boolean }
defined trait IntChecker

scala> implicit val intIntChecker: IntChecker[Int] = new IntChecker[Int] { override def isInt = true }
intIntChecker: IntChecker[Int] = $anon$1@585dd35c

scala> implicit def otherIntChecker[A: NotAnInt]: IntChecker[A] = new IntChecker[A] { override def isInt = false }
otherIntChecker: [A](implicit evidence$1: NotAnInt[A])IntChecker[A]

该类型类可以按预期使用:
scala> def printIntStatus[T: IntChecker](t: T): Unit = { println(implicitly[IntChecker[T]].isInt()) }
printIntStatus: [T](t: T)(implicit evidence$1: IntChecker[T])Unit

scala> printIntStatus(3)
true

scala> printIntStatus("three")
false

但是,以下内容也可以编译:
scala> def printIntStatusWithBug[T](t: T): Unit = { println(implicitly[IntChecker[T]].isInt()) }
printIntStatusWithBug: [T](t: T)Unit

scala> printIntStatusWithBug(3)
false

scala> printIntStatusWithBug("three")
false

我不希望第二个函数编译,因为不应该有隐式 IntChecker[T]可用的。我期待 everythingIsNotAnInt是这个问题的原因,但我想不出办法解决这个问题。

我对这种方法失败的原因以及如何实现相同目标的替代方法感兴趣。谢谢你。

最佳答案

考虑以下替代实现(使用 Sabin 的 type inequalities )

trait =!=[A, B]
implicit def neq[A, B] : A =!= B = null
implicit def neqAmbig1[A] : A =!= A = null
implicit def neqAmbig2[A] : A =!= A = null

trait IntChecker[A] {
def isInt(): Boolean
}

object IntChecker {
import scala.reflect.ClassTag
implicit val intIntChecker: IntChecker[Int] = () => true
implicit def notIntIntChecker[T: ClassTag](implicit ev: T =!= Int): IntChecker[T] = () => false
}

def printIntStatus[T: IntChecker](t: T) = implicitly[IntChecker[T]].isInt()

import IntChecker._
printIntStatus(3)
printIntStatus("three")

哪个输出
res0: Boolean = true
res1: Boolean = false

然而,我们忘记了 IntChecker 的错误实现边界
def printIntStatusWithBug[T](t: T) = implicitly[IntChecker[T]].isInt()

由于有 T: ClassTag 不应该编译绑定(bind)在
implicit def notIntIntChecker[T: ClassTag](implicit ev: T =!= Int)

给出编译器错误
could not find implicit value for parameter e: IntChecker[T]
def printIntStatusWithBug[T](t: T) = implicitly[IntChecker[T]].isInt()
^

关于scala - 如何在 Scala 中正确使用模棱两可的隐式进行类型否定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58512830/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com