Scala高级类型语法

Scala高级类型语法,scala,generics,types,higher-kinded-types,Scala,Generics,Types,Higher Kinded Types,我不熟悉Scala,也不熟悉更高级的类型。我想写这样的东西 trait Actor[E[Dependency] <: Event[Dependency]] { def execute(dependency: Dependency): Unit } trait Event[Data] { val payload: Data } case class FooEvent(payload: Foo) extends Event[Foo] class FooActor extends

我不熟悉Scala,也不熟悉更高级的类型。我想写这样的东西

trait Actor[E[Dependency] <: Event[Dependency]] {
  def execute(dependency: Dependency): Unit
}
trait Event[Data] {
   val payload: Data
}
case class FooEvent(payload: Foo) extends Event[Foo]

class FooActor extends Actor[FooEvent] {
   def execute(dependency: Foo) = {}
}
…我想定义一个事件和一个这样的演员

trait Actor[E[Dependency] <: Event[Dependency]] {
  def execute(dependency: Dependency): Unit
}
trait Event[Data] {
   val payload: Data
}
case class FooEvent(payload: Foo) extends Event[Foo]

class FooActor extends Actor[FooEvent] {
   def execute(dependency: Foo) = {}
}
但是,我不能在execute方法中引用类型参数依赖关系-编译器不知道它

不能,因为它不是
Actor
的参数。考虑

val actor = new Actor[Event] // E is Event
actor.execute(???) // what argument is this supposed to take? I.e. what is Dependency for Actor[Event]?

更新:根据您的编辑,
[Dependency,T我将尝试改进Alexey的答案-他是对的,但他太短了。但我必须说,我不是HKT的专家,我想我才刚刚开始理解这个概念

在你的代码中,
E[Dependency]
E[\u]
相同,这表示你有
E
,其中有一些类型作为参数。这意味着你不会将
Dependency
作为类型进行操作。你也不会将
E
E[Dependency]作为类型进行操作
作为类型。
E
是一个类型构造函数,
E[Dependency]
是一个存在类型,如果我理解正确的话。请注意

trait Actor[E[D] <: Event[D]] { def execute(d: E) {} }

基本上,诀窍是定义
类型p
这是我们的
依赖关系
类型E=Event[p]
这总是
事件[Dependency]
然后你可以通过定义
P
来使用actor,而不必像已经定义的那样定义
E
。不确定它是否解决了问题,但它看起来像是一种方法。这里也有太多的类型,一些类型如
IntActor
是不必要的。我把它们放在这里是为了更容易理解这个示例

不确定我遵循你的论点,所以我添加了更多的细节,应该可以告诉你我在做什么。所以我实际上是说,Actor依赖于某个类型,而它本身依赖于另一个类型。我没有办法将execute方法定义为接受类型依赖?这只是编译器的一个限制,还是根本上是什么不可能?事实上,我已经混合了两种答案,现在我认为我更好地理解了HKTs的目的。我选择Archeg,因为我觉得这里有更多的信息供以后阅读的人参考。感谢你们两位的帮助。这很有用,但只是为了澄清:尽管类似的语法。我现在不在我的计算机上,但我认为你的第一个示例实际上是编译的。我认为我昨天简单地这样做了。你的最后一个示例很有趣,但并没有真正解决我的问题,因为方法定义上的类型参数与trait上的类型参数没有关系。@RyanWorsley我认为你的示例不适合我您需要使用HKT。您需要将
依赖项
定义为一个类型,以便能够指定它。从逻辑上讲,您想要的确切内容是不可能的,请参见Alexey的示例。如果不指定
数据
类型,您无法创建
参与者
实例,因为
参与者
依赖于
数据
你说得对,我不需要这样做,事实上,我在我的原始问题中展示了如何在没有HKTs的情况下完成。我之所以要走这条路,是因为在我看来,编译器有足够的信息让我捕获并使用类型依赖关系。这使得整体语法更好,因为我只需要指定一个类型参数如果你仔细想想,FooActor的定义告诉编译器依赖的类型,所以我认为HKT几乎就像类型的模式匹配,我可以分解类型结构并使用部分。
trait Actor[E[D] <: Event[D]] { def execute[B](d: E[B]) {} }
  trait Event[P] {
    val payload: P
  }

  case class FooEvent(payload: Int) extends Event[Int]

  trait BaseActor {
    type E = Event[P]
    type P
    def execute(dep: P)
    def runEvent(event: E)
  }

  trait IntActor extends BaseActor {
    type P = Int
  }

  class FooActor extends IntActor {
    def execute(dependency: P) = {}
    def runEvent(event: E) = {}
  }

  val c = new FooActor()
  c.runEvent(FooEvent(5))
  c.execute(5)