Scala 3 中 Union Type 和 Either 之间的隐式转换

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

我正在尝试在 Scala 3 中开发一个从类型

Error | A
到类型
Either[Error, A]
的隐式转换器。转换器的代码如下:

object MyConversions:
  given unionTypeToEither[Error, A]: Conversion[Error | A, Either[Error, A]] with
    def apply(value: Error | A): Either[Error, A] = value match
      case error: Error => Left(error)
      case a: A         => Right(a)

转换器应使用以下代码:

import in.rcard.raise4s.MyConversions.unionTypeToEither

val actual: String | Int = 42
val actualEither: Either[String, Int] = actual

编译器给了我以下错误:

[error] 90 |    val actualEither: Either[String, Int] = actual
[error]    |                                            ^^^^^^
[error]    |                                       Found:    (actual : String | Int)
[error]    |                                       Required: Either[String, Int]
[error]    |
[error]    | longer explanation available when compiling with `-explain`
[error] one error found

有人可以帮助我吗?

scala implicit-conversion scala-3 union-types
1个回答
0
投票

问题来自于

Either[A, B]
A | B
之间的语义差异。

A | B
B | A
相同,任何
A
A | Nothing
相同 - 虽然组合 2 种类型(与
|
)始终是明确的,但分解始终是不明确的。如果没有例如,你就无法做到这一点使用自定义逻辑和附加假设编写一些宏。

根据我的经验,如果你尝试使用推理,例如通过将其传递给类似以下内容来分割

A | B

[X, Y](value: X | Y): Either[X, Y] = ...

你实际上得到的是

Either[A | B, Nothing]
或者一些有点无用的东西。

作为对您的类型有一定了解的人,您可能会假设:

  • A
    B
    的最低上限为
    Any
    /
    AnyRef
    /
    AnyVal
  • 没有
    A <:< B
    也没有
    B <:< A
    关系
  • 类型擦除不会丢失任何内容,因此可以在运行时安全地比较它们

但作为一个非常普遍的规则,如果所有代码都知道类型是

<: Any
,那么编译器就没有什么可处理的,并且可能没有人尝试处理类型推断以使其以某种智能方式工作.

假设您有某种确定性的方法来决定哪个组件最先出现,哪个组件最后出现(即:

A | B
中左边的内容和右边的内容,因为它与
B | A
相同),您会仍然需要自己编写分解逻辑,可能是通过编写宏并接受某些情况无法通过它来处理。

© www.soinside.com 2019 - 2024. All rights reserved.