scala3扩展方法类型参数



这是我的scala2代码到scala3的直接转换

trait Narrow[F[_], A, B <: A: ClassTag]:
def apply(fa: F[A]): F[B]
extension [F[_], A] (fa: F[A]):
def narrow[B: ClassTag] (using op: Narrow[F, A, B]): F[B] = op(fa)

我需要在调用站点指定窄操作的类型,但是扩展方法不允许这种语法。对于这种限制,有什么最好的解决办法?

这样做的目的是能够缩小集合/try/athing中的类型。窄类型类将平面映射内部的任何内容,比较运行时类型,如果它匹配将B封装在F中,或者以其他方式返回空的F

trait A
trait B extends A
object A extends A
object B extends B
val bb: List[B] = List(A, A, B, B, A)
.narrow[B]
assert(bb == List(B, B))

如果你能处理丑陋的问题,你可以使用多态函数:

extension [F[_], A] (fa: F[A]):
def narrow() = [B <: A] => (using op: Narrow[F, A, B]) => op(fa)

然后可以用foo.narrow()[String]调用它。它在Scastie。

narrow()是必要的,因为如果没有它,类型参数将转到扩展,而不是多态函数。

在未来,Scala 3可能会允许类型参数直接指向扩展中的方法,但现在,您可以继续使用Scala 2隐式类,并在下一个版本后对其进行更改:

implicit class NarrowOps[F[_], A](fa: F[A]):
def narrow[B <: A](using op: Narrow[F, A, B]) = op(fa)

Scastie

旁注:您的扩展中不再需要B: ClassTag,尽管我相信您确实需要使用绑定的B <: A

我无法在呼叫站点上使用()。我决定尝试使用只带类型参数的apply方法隐式转换为类型。

trait NarrowTypeClass[F[_], A, B <: A: ClassTag]:
def apply(fa: F[A]): F[B]
given [F[_], A] as Conversion[F[A], Narrowable[F, A]] = Narrowable(_)
sealed class Narrowable [F[_], A] (fa: F[A]):
def narrow[B <: A: ClassTag] (using op: NarrowTypeClass[F, A, B]): F[B] = op(fa)

这似乎起到了的作用

最新更新