Generics Scala中具有联合类型的泛型数据结构
我试图大致实现以下目标:Generics Scala中具有联合类型的泛型数据结构,generics,scala,types,Generics,Scala,Types,我试图大致实现以下目标: /* I assume that we have some types S and T */ sealed trait Container[U] class SContainer(s: S) extends Container[S] class TContainer[U <: T](u: U) extends Container[U] /* this requires something more */ def invoke[U](f: String =>
/* I assume that we have some types S and T */
sealed trait Container[U]
class SContainer(s: S) extends Container[S]
class TContainer[U <: T](u: U) extends Container[U]
/* this requires something more */
def invoke[U](f: String => U): Container[U]
因为它们在运行时具有相同的类型
如何在
invoke
上表达这样的类型约束?我认为下面的方法可以奏效。我不知道你的t
和S
是什么,所以我正在尝试这些
type T = AnyVal
type S = String
您可以使用视图绑定:
object Container {
implicit def stuffS(s: S): Container[S] = new SContainer(s)
implicit def stuffT[U <: T](u: U): Container[T] = new TContainer(u)
}
sealed trait Container[U]
case class SContainer(s: S) extends Container[S]
case class TContainer[U <: T](u: U) extends Container[T]
这些电话是有效的:
invoke(_.size) // -> Container[T] = TContainer(5)
invoke(_.reverse) // -> Container[S] = SContainer(ollah)
这是不允许的:
invoke(Symbol(_))
编辑
如果您想要的是容器[U]
而不是容器[T]
,它会变得更简单:
object Container {
implicit def stuffS(s: S): Container[S] = new SContainer(s)
implicit def stuffT[U <: T](u: U): Container[U] = new TContainer(u)
}
sealed trait Container[U]
case class SContainer(s: S) extends Container[S]
case class TContainer[U <: T](u: U) extends Container[U]
def invoke[A <% Container[A]](f: String => A): Container[A] = f("hallo")
invoke(_.size) // Container[Int]
invoke(_.reverse) // Container[String]
invoke(Symbol(_)) // forbidden
对象容器{
隐式def填充:容器=新容器
隐式def stuffT[U我认为应该将容器的定义与容器本身可接受的类型的定义分开
首先,让我们假设(例如)s是String,T是一个伪类
class A
class B extends A
type T = A
type S = String
现在,让我们使用typeclass模式将s和T的子类定义为容器的可接受内容:
sealed class AcceptableContent[X] private()
object AcceptableContent {
implicit object SAcceptable extends AcceptableContent [S]
implicit def TAcceptable[U <: T] = new AcceptableContent[U]
}
上下文绑定的:AcceptableContent
表示,只有当范围中存在一个隐式的AcceptableContent[R]时,才可以接受一个R,这正是您想要的。
事实上,现在:
scala> new Container("test")
res0: Container[java.lang.String] = Container@1d1fceed
scala> new Container(new A)
res1: Container[A] = Container@631803fb
scala> new Container(new B)
res2: Container[B] = Container@67446579
scala> new Container(true) // Ok, Container accepts String, A, B but not Boolean
<console>:12: error: could not find implicit value for evidence parameter of type AcceptableContent[Boolean]
这里有一个矛盾。您将TContainer
定义为Container[T]
的子类型,同时希望调用返回容器[U]
。因此,首先,您需要决定是要容器[T]
还是容器[U]
。哎哟。你说得对,应该是容器[U]
。看起来我把原来的问题简化了一点,但你的解决方案对我提出问题的方式来说是非常有效和不错的。我知道你的意思:)祝你好运!
sealed class AcceptableContent[X] private()
object AcceptableContent {
implicit object SAcceptable extends AcceptableContent [S]
implicit def TAcceptable[U <: T] = new AcceptableContent[U]
}
class Container[R : AcceptableContent](content: R)
scala> new Container("test")
res0: Container[java.lang.String] = Container@1d1fceed
scala> new Container(new A)
res1: Container[A] = Container@631803fb
scala> new Container(new B)
res2: Container[B] = Container@67446579
scala> new Container(true) // Ok, Container accepts String, A, B but not Boolean
<console>:12: error: could not find implicit value for evidence parameter of type AcceptableContent[Boolean]
def invoke[N : AcceptableContent](f: String => N) : Container[N] = new Container(f("test"))