当类型参数具有公共类型时,Scala添加扩展方法
Posted
技术标签:
【中文标题】当类型参数具有公共类型时,Scala添加扩展方法【英文标题】:Scala add extension method when the type params have a common type 【发布时间】:2022-01-01 01:52:36 【问题描述】:我有一个类型 Foo[+A, +B]
和一个类型 Bar[+B]
。我想像这样将扩展方法bar
添加到Foo
implicit class FooSyntax[A](foo: Foo[A, Bar[A]])
def bar: A = ???
所以扩展方法只适用于B
是Bar[A]
的情况。因此,以下所有内容都应该编译——
trait Fruit
trait Apple extends Fruit
trait Banana extends Fruit
def foo0: Foo[Apple, Bar[Banana]] = ???
def foo1: Foo[Apple, Bar[String]] = ???
def foo2: Foo[Apple, Bar[Apple]] = ???
def foo3: Foo[Apple, List[Apple]] = ???
foo0.bar // Fruit
foo1.bar // Object
foo2.bar // Apple
对于我的用例,我希望能够在没有 FooSyntax
的情况下使用隐式要求来执行此操作,这样该方法始终可用并且易于发现,但是只有在满足类型条件时才可以调用它.这就是我到目前为止所做的——
trait Foo[+A, +B]
def bar[C <: A](implicit evA: A <:< C, evB: B <:< Bar[C]): C
不用说,这是行不通的。
【问题讨论】:
我希望该方法始终可用以便更好地发现,但只有在满足条件时才可以调用它。 【参考方案1】:trait Foo[+A, +B]
def bar(implicit ev: FooBar[A, B]): ev.Out
trait Bar[+B]
trait FooBar[-A, -B]
type Out
object FooBar
type Aux[A] = FooBar[A, Bar[A]] type Out = A
implicit def x[A]: FooBar.Aux[A] =
new FooBar[A, Bar[A]]
override type Out = A
【讨论】:
您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。【参考方案2】:您需要做的就是从C
中删除绑定的类型,并留下隐含的证据来完成它的工作。
trait Bar[+B]
trait Foo[+A, +B]
def bar[C](implicit ev1: A <:< C, ev: B <:< Bar[C]): C = ???
那么你可以这样做(如预期的那样):
foo0.bar // Fruit
foo1.bar // Object
foo2.bar // Apple
可以看到代码运行here
【讨论】:
为什么在scala 2.13.x
中不起作用?
@JohnyTKoshy 啊,我的错。我忘了 Scastie 默认使用 Scala 3。嗯,类型推断算法在3.0.0
中得到了改进,看来旧版本不能做你想做的了。
这不是我的问题。 OP 可能正在使用3.0.0
。我在2.13.x
中尝试了同样的方法。无论如何,谢谢。
是的,我正在努力让它在 Scala 中工作 2.13.7
以上是关于当类型参数具有公共类型时,Scala添加扩展方法的主要内容,如果未能解决你的问题,请参考以下文章
在Fortran中,在扩展定义中,如何将公共过程设置为私有?