gpt4 book ai didi

scala - 尝试实现 `Absurd` 类型类时的隐式错误

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

我正在尝试实现 Absurd typeclass (as seen in Haskell's Data.Boring library)在斯卡拉。

我可以定义一个 Absurd Nothing 的实例.
不幸的是,当我尝试为 Either 定义一个荒谬的实例时, 我得到一个缺失的隐式错误

sealed trait Absurd[A] {
def absurd[X](a: A): X
}

object Absurd {
def apply[A: Absurd, B](a: A):B = implicitly[Absurd[A]].absurd[B](a)

implicit val absurdForNothing: Absurd[Nothing] = new Absurd[Nothing]{
override def absurd[X](a: Nothing): X = a
}

implicit def absurdForEither[A: Absurd, B: Absurd]: Absurd[Either[A, B]] = new Absurd[Either[A, B]]{
override def absurd[X](a: Either[A,B]): X = a match {
case Left(a) => Absurd[A, X](a)
case Right(b) => Absurd[B, X](b)
}
}
}

这编译:

implicitly[Absurd[Nothing]]

这无法编译:

implicitly[Absurd[Either[Nothing, Nothing]]]

我正在使用 Scala 版本“2.13.2”。

值得注意的是,以下非常相似的代码(不涉及 Nothing )确实可以编译:

trait SomeTypeclass[A]
case class SomeInstance()

object SomeTypeclass {
implicit val someTypeclassForSomeInstance: SomeTypeclass[SomeInstance] = new SomeTypeclass[SomeInstance] {}

implicit def someTypeclassForEither[A: SomeTypeclass, B: SomeTypeclass]: SomeTypeclass[Either[A, B]] = new SomeTypeclass[Either[A, B]] {}
}
object SomeApplicationCode {
implicitly[SomeTypeclass[Either[SomeInstance, SomeInstance]]]
}

最佳答案

感谢 Dmytro 的评论,我找到了 this post suggesting a workaround为此 bug .

简而言之,我们可以定义一个类型别名 Empty.T对于 Nothing 的子类型

object Empty{
type T <: Nothing
}

Nothing没有值,也没有子类型, Empty.T也将没有值。这让我们可以编写我们的 Absurd 实例:

object Absurd {
def apply[A: Absurd, B](a: A):B = implicitly[Absurd[A]].absurd[B](a)

implicit val absurdForEmptyT: Absurd[Empty.T] = new Absurd[Empty.T]{
override def absurd[X](a: Empty.T): X = a
}

implicit def absurdForEither[A:Absurd, B: Absurd]: Absurd[Either[A, B]] = new Absurd[Either[A, B]]{
override def absurd[X](a: Either[A,B]): X = a match {
case Left(a) => Absurd[A,X](a)
case Right(b) => Absurd[B, X](b)
}
}
}

这有效!以下将编译:

implicitly[Absurd[Either[Empty.T, Empty.T]]]

就像:

implicitly[Absurd[Either[Nothing, Nothing]]]

由于我正在移植 Haskell 代码,它不必担心变化,因此定义我们自己的空类型作为解决方法同样有效:

sealed trait Empty

object Absurd {
def apply[A: Absurd, B](a: A):B = implicitly[Absurd[A]].absurd[B](a)

implicit val absurdForEmpty: Absurd[Empty] = new Absurd[Empty]{
override def absurd[X](a: Empty): X = ???
}
// ...
}

这有效,但我个人更喜欢第一种方法,因为它不会忽略 Empty 类型 Nothing这已经内置在 Scala 中,并且因为它不依赖于我们使用 ???写首字母 Absurd[Empty]实例。

关于scala - 尝试实现 `Absurd` 类型类时的隐式错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62003214/

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