Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.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
在Scala中创建self类型的实例_Scala_Scala Collections_Implicit_Higher Kinded Types - Fatal编程技术网

在Scala中创建self类型的实例

在Scala中创建self类型的实例,scala,scala-collections,implicit,higher-kinded-types,Scala,Scala Collections,Implicit,Higher Kinded Types,我不确定这个问题的标题是否用Scala类型的术语正确表达。。。我面临的问题有点类似于Scala集合使用CanBuildFrom管理的问题 有更高级类型的层次结构和这些类型的容器(不一定是集合)的并行层次结构。例如,过滤容器中的项的操作应返回执行该操作的容器的确切类型,并过滤这些项 我遇到的问题是,如果不显式地传递容器类型,我无法找到将隐式证据要求限制为要构造的确切容器类型的正确方法 下面是我正在处理的设置的简化版本。我希望能就如何处理这个问题提出一些建议 @implicitNotFound(ms

我不确定这个问题的标题是否用Scala类型的术语正确表达。。。我面临的问题有点类似于Scala集合使用
CanBuildFrom
管理的问题

有更高级类型的层次结构和这些类型的容器(不一定是集合)的并行层次结构。例如,过滤容器中的项的操作应返回执行该操作的容器的确切类型,并过滤这些项

我遇到的问题是,如果不显式地传递容器类型,我无法找到将隐式证据要求限制为要构造的确切容器类型的正确方法

下面是我正在处理的设置的简化版本。我希望能就如何处理这个问题提出一些建议

@implicitNotFound(msg = "Cannot construct a ${B} from ${A} with arguments of type ${Args}.")
trait CanConstruct[A, -Args, +B] {
  def apply(args: Args): B
}

class A1

trait C1[A <: A1] {
  def a: A
  def active: Boolean
}
trait C1s[C <: C1[A] forSome {type A <: A1}] {
  def values: Seq[C]
  // @note something like def active[From <: C1s[_]]... will find implicits
  //       but will be happy to use a super-type's implicit for a subtype's      
  def active[To[_ <: C]](implicit builder: CanConstruct[To[_], Seq[C], To[C]]): To[C] =
    builder(values.filter(_.active))
}

class C2(val a: A1, val active: Boolean) extends C1[A1]
class C2s[C <: C2](val values: Seq[C]) extends C1s[C]
object C2s {
  class C2CanConstruct[C <: C2] extends CanConstruct[C2s[_], Seq[C], C2s[C]] {
    def apply(args: Seq[C]): C2s[C] = new C2s(args)
  }
  implicit def C2CanConstruct[C <: C2] = new C2CanConstruct[C]
}

class C3s[C <: C2](values: Seq[C]) extends C2s[C](values)
object C3s {
  class C3CanConstruct[C <: C2] extends CanConstruct[C3s[_], Seq[C], C3s[C]] {
    def apply(args: Seq[C]): C3s[C] = new C3s(args)
  }
  implicit def C3CanConstruct[C <: C2] = new C3CanConstruct[C]
}

val a = new A1()
val cs = Seq(new C2(a, true), new C2(a, false))

// How can active pick the corresponding C?CanConstruct implicit automatically?
// i.e., new C2s(cs).active returns C2s[...] and 
//       new C3s(cs).active returns C3s[...]
new C2s(cs).active[C2s]
new C3s(cs).active[C3s]
@implicitNotFound(msg=“无法使用${Args}类型的参数从${a}构造${B}”。)
特征CanConstruct[A,-Args,+B]{
def应用(参数:参数):B
}
A1类

特质C1[A编辑2:你链接的问题的固定版本。问题是
C1.T
/
C2.T
的每次使用都是不同的,所以
C关于你更新的问题(使用“真实世界”代码)尝试以下修改版本的@user的第二种方法,将抽象类型成员
修改为
。我在
C1s
(必需)、
C2s
(必需)、
C3s
(可选)中将
的参数上限修改为
(否则将
重写为
不起作用)并使类型类
CanConstruct
相对于
to
协变(否则找不到隐式)

@annotation.implicitNotFound(msg=“无法使用${Args}类型的参数从${from}构造${To}”。)
特征CanConstruct[+From,-Args,+To]{
def应用(参数:参数):到
}
类配置

trait C1[Cfg为什么不将
To
作为类型参数(我的意思是,对于您的类)?@user In
C1s
?它变得相当混乱,因为在实际的系统中,类型有更复杂的参数化。我正在寻找一种方法来避免这个样板。@Sim如何主动地自动选择相应的隐式?你是什么意思?你想
到[@Sim实际上你没有将
约束到[@Sim我将
到[@Sim]吗[;谢谢你的建议。我考虑过这一点,并决定反对它,因为将这种方法应用于整个系统将导致将与类型相关的大多数行为移动到隐式,这是一种反模式,原因很多,与可用性、可维护性等有关。@Sim我添加了一种与类型成员相关的替代方法,requiring只是多一点样板。另外,我建议使用不同类型的
From
To
谢谢您的额外努力:我喜欢类型成员方法。不幸的是,实际系统更复杂:C1包含一个触发不兼容类型重写错误的类型参数(Scastie:)。我认为问题的简单表述就足够了,这是不好的。我将为这个问题增加额外的工作,以调整答案。@Sim有效。只需替换
T感谢您进一步探讨这个问题。我听到您对这里的复杂性表示关注,并对如何简化它的想法持开放态度。real域如下。
Config
是可序列化的“项目配置”的层次结构。
Ci
是“项目”的层次结构根据项目配置和其他信息(例如,交付计划)创建。
Ci
是具有与其所持有内容类型相关的特定行为的
Ci
集合。例如,对于具有交付计划的项目,可以筛选到需要在特定日期交付的项目。要启动,集合不能扩展
Seq
。虽然我已经接受了@user的答案,但您的指导非常有用,我也会找到一种方法奖励这个答案。
@annotation.implicitNotFound(
  msg = "Cannot construct a ${To} from ${From} with arguments of type ${Args}."
)
trait CanConstruct[+From, -Args, +To] {
  def apply(args: Args): To
}

class Config

trait C1[Cfg <: Config] {
  type Config = Cfg
  def config: Config
}
object C1 {
  type T = C1[_]
}
trait C1s[C <: C1.T] {
  type From <: C1s[_]
  type To[T <: C] <: C1s[T]
  def values: Seq[C]
  protected def builder: CanConstruct[From, Seq[C], To[C]]
  def filter(f: C => Boolean): To[C] =
    builder(values.filter(f))
}

class C2[Cfg <: Config](val config: Cfg, val active: Boolean) extends C1[Cfg]
object C2 {
  type T = C2[_]
}
abstract class C2s[C <: C2.T](val values: Seq[C]) extends C1s[C] {
  type From <: C2s[_]
  type To[T <: C] <: C2s[T]
}
object C2s {
  def apply[C <: C2.T](values: Seq[C]) =
    new C2s(values) { 
      type From = C2s[_]
      type To[T2 <: C] = C2s[T2] 
      val builder = new CanConstruct[C2s[_], Seq[C], RefinedC2s[C]] {
        def apply(args: Seq[C]) = C2s(args)
      }
    }
}

//Final because its type members are invariant
final class C3s[C <: C2.T](values: Seq[C]) extends C2s[C](values) {
  type From = C3s[_]
  type To[T <: C] = C3s[T]
  protected val builder = new CanConstruct[C3s[_], Seq[C], C3s[C]] {
    def apply(args: Seq[C]): C3s[C] = new C3s(args)
  }
}

val cfg = new Config
val cs = Seq(new C2(cfg, true), new C2(cfg, false))

val c2s = C2s(cs).filter(_.active).filter(_.active)
val c3s = new C3s(cs).filter(_.active).filter(_.active)
trait C1 {
  def active: Boolean
}
trait C1s[C <: C1] {
  type To[T <: C] <: C1s[T]
  //R is so that it can be RefinedC2s instead of C2s
  def active[R <: To[C]](implicit builder: CanConstruct[To[_], Seq[C], R]): R = 
    builder(values.filter(_.active))
}

class C2s[C <: C2](val values: Seq[C]) extends C1s[C] {
  type To[T <: C2] <: C2s[T]
}
object C2s {
  type RefinedC2s[T <: C2] = C2s[T] { type To[T <: C2] = C2s[T] }
  def apply[C <: C2](values: Seq[C]) = new C2s(values) { type To[T <: C2] = C2s[T] }
  class C2CanConstruct[C <: C2] extends CanConstruct[C2s[_], Seq[C], RefinedC2s[C]] {
    def apply(args: Seq[C]) = C2s(args)
  }
}

class C3s[C <: C2](values: Seq[C]) extends C2s[C](values) {
  type To[T <: C2] = C3s[T]
}
val c2s = C2s(cs).active.active.active.active.active
val c3s = new C3s(cs).active.active
import scala.language.existentials

@annotation.implicitNotFound(msg = "Cannot construct a ${B} from ${A} with arguments of type ${Args}.")
trait CanConstruct[+A, -Args, B] {
  def apply(args: Args): B
}

trait C1 {
  def active: Boolean
}
trait C1s[C <: C1] {
  def values: Seq[C]
}

implicit class CsOps[C <: C1, Cs[_ <: C] <: C1s[_ <: C]](cs: Cs[C]) {
  def active(implicit builder: CanConstruct[Cs[Nothing], Seq[C], Cs[C]]): Cs[C] = 
    builder(cs.values.filter(_.active))
}

class C2(val active: Boolean) extends C1
class C2s[C <: C2](val values: Seq[C]) extends C1s[C]

object C2s {
  class C2CanConstruct[C <: C2] extends CanConstruct[C2s[Nothing], Seq[C], C2s[C]] {
    def apply(args: Seq[C]): C2s[C] = new C2s(args)
  }
  implicit def C2CanConstruct[C <: C2] = new C2CanConstruct[C]
}

class C3s[C <: C2](values: Seq[C]) extends C2s[C](values)

object C3s {
  class C3CanConstruct[C <: C2] extends CanConstruct[C3s[Nothing], Seq[C], C3s[C]] {
    def apply(args: Seq[C]): C3s[C] = new C3s(args)
  }
  implicit def C3CanConstruct[C <: C2] = new C3CanConstruct[C]
}

val cs = Seq(new C2(true), new C2(false))

val c2s: C2s[C2] = new C2s(cs).active
val c3s: C3s[C2] = new C3s(cs).active

c2s -> C2s(List(C2(true))): C2s[C2]
c3s -> C2s(List(C2(true))): C3s[C2]
@annotation.implicitNotFound(msg = "Cannot construct a ${To} from ${From} with arguments of type ${Args}.")
trait CanConstruct[+From, -Args, +To] {
  def apply(args: Args): To
}

class Config

trait C1[Cfg <: Config] {
  type Config = Cfg
  def config: Config
}
object C1 {
  type T = C1[A] forSome {type A <: Config}
}
trait C1s[C <: C1.T] {
  type To[T <: /*C1.T*/C] <: C1s[T]
  def values: Seq[C]
  def filter[R <: To[C]](f: C => Boolean)(implicit builder: CanConstruct[To[_], Seq[C], R]): R =
    builder(values.filter(f))
}

class C2[Cfg <: Config](val config: Cfg, val active: Boolean) extends C1[Cfg]
object C2 {
  type T = C2[A] forSome {type A <: Config}
}
class C2s[C <: C2.T](val values: Seq[C]) extends C1s[C] {
  type To[T <: /*C2.T*/C] <: C2s[T]
}
object C2s {
  type RefinedC2s[C <: C2.T] = C2s[C] { type To[T <: /*C2.T*/C] = C2s[T] }
  def apply[C <: C2.T](values: Seq[C]) = new C2s(values) { type To[T <: /*C2.T*/C] = C2s[T] }
  class C2CanConstruct[C <: C2.T] extends CanConstruct[C2s[_], Seq[C], RefinedC2s[C]] {
    def apply(args: Seq[C]) = C2s(args)
  }
  implicit def C2CanConstruct[C <: C2.T] = new C2CanConstruct[C]
}

class C3s[C <: C2.T](values: Seq[C]) extends C2s[C](values) {
  type To[T <: /*C2.T*/C] = C3s[T]
}
object C3s {
  class C3CanConstruct[C <: C2.T] extends CanConstruct[C3s[_], Seq[C], C3s[C]] {
    def apply(args: Seq[C]): C3s[C] = new C3s(args)
  }
  implicit def C3CanConstruct[C <: C2.T] = new C3CanConstruct[C]
}

val cfg = new Config
val cs = Seq(new C2(cfg, true), new C2(cfg, false))

implicitly[CanConstruct[C2s[_], Seq[C2[Config]], C2s[C2[Config]]]]
implicitly[CanConstruct[C3s[_], Seq[C2[Config]], C3s[C2[Config]]]]

val c2s = C2s(cs).filter(_ => true)
val c3s = new C3s(cs).filter(_ => true)
// val idontwork = new C2s(cs).filter(_ => true) //Doesn't work because `To` is abstract

c2s
c3s