[英]Restrict function generic type parameters
Having following structure:具有以下结构:
trait ParentType
trait ChildType extends ParentType
case class FooBar[+T <: ParentType](s: String, data: T)
object FooBar {
def apply[T <: ChildType](i: Int, data: T): FooBar[T] = new FooBar(s"$i", data)
}
case class Foo(a: Int) extends ParentType
case class Bar(s: String) extends ChildType
def function1[T <: ParentType](obj: FooBar[T]): Unit = ()
def function2[T <: ChildType](obj: FooBar[T]): Unit = ()
Is possible(and in what way) to change the signature(with generics declaration) of function1
and function2
such that function1
can only except parameters of FooBar
with type T
that is direct descendant of ParentType
(and prohibit any T
that is direct descendant of ChildType
) and function2
in another way around - except only parameters with T
that are direct descendants of ChildType
and prohibit all ParentType
T
's是否可以(以及以何种方式)更改
function1
和function2
的签名(使用 generics 声明),以便function1
只能排除类型为T
的FooBar
的参数,该类型是ChildType
的直接后代(并禁止任何T
是ParentType
的直接后代) 和function2
以另一种方式 - 除了只有带有T
的参数是ChildType
的直接后代并禁止所有ParentType
T
的
In other words this shouldn't compile换句话说,这不应该编译
function1(FooBar("a", Bar("1"))) //because Bar is not direct descendant of ParentType
The question does not make very much sense, I am afraid, but to answer what you wrote in comments:恐怕这个问题没有多大意义,但要回答您在评论中写的内容:
I want function2 to accept "containers" FooBars of Mammals only
我希望function2只接受哺乳动物的“容器”FooBars
So, it should be def function2(m: Foobar[Mammal])
所以,它应该是
def function2(m: Foobar[Mammal])
and function1 - all other group types of animals(but not mammals)
和 function1 - 所有其他组类型的动物(但不是哺乳动物)
This is a weird requirement.这是一个奇怪的要求。 If you are sure you need this (I really, really doubt you actually do), I suggest something like this:
如果你确定你需要这个(我真的,真的怀疑你真的需要),我建议这样:
trait NotMammal extends Animal
class Fish extends NotMammal
class Reptile extends NotMammal
...
def funcction1(n: Foobar[NotMammal]) = ???
With help of @LuisMiguelMejíaSuárez (see his comments to the question) I managed to achieve what I wanted.在@LuisMiguelMejíaSuárez 的帮助下(请参阅他对问题的评论),我设法实现了我想要的。 So, taking into account as well that I need context bound for
Arbitrary
from scalacheck to be in these functions declarations, Luis suggestion to use shapless(in particular I found out that <:!<
can solve my problem) helped因此,考虑到我需要从 scalacheck 为
Arbitrary
绑定的上下文在这些函数声明中,Luis 建议使用 shapless(特别是我发现<:!<
可以解决我的问题)帮助
import shapless._
def function1[T <: ParentType](obj: FooBar[T])(implicit: arb: Arbitrary[T], ev: T <:!< ChildType): Unit = ()
def function2[T <: ChildType : Arbitrary](obj: FooBar[T]): Unit = ()
Unfortunately I didn't manage to achieve the override of function1
(just with different ev
types), but having those functions with different names I can reuse function1
from function2
(I need just to call function1
with explicit parameter for <:!<
instance which is shapeless.nsub
).不幸的是,我没有设法实现对
function1
的覆盖(只是使用不同的ev
类型),但是有了这些具有不同名称的函数,我可以从function2
重用function1
(我只需要使用<:!<
实例的显式参数调用function1
是shapeless.nsub
)。
So with this solution any ChildType
instance can't be applied to function1
(at least as is) because such application results in因此,使用此解决方案,任何
ChildType
实例都不能应用于function1
(至少按原样),因为这样的应用程序会导致
ambiguous implicit values:
both method nsubAmbig1 in package shapeless of type [A, B >: A]A <:!< B
and method nsubAmbig2 in package shapeless of type [A, B >: A]A <:!< B
match expected type Bar <:!< ChildType
I guess this is what was designed behind usage of <:!<
type(but if explicitly to specify an instance of <:!<
it will work)我想这是使用
<:!<
类型背后的设计(但如果明确指定<:!<
的实例,它将起作用)
Here is a link to scastie worksheet to try out the problem这是一个链接到 scastie 工作表来尝试这个问题
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.