Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Generics Scala中具有联合类型的泛型数据结构_Generics_Scala_Types - Fatal编程技术网

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"))