繁体   English   中英

Scala更高级的kinded类型语法

[英]Scala higher kinded type syntax

我是Scala的新手,也是更高级别的新手。 我想写这样的东西;

trait Actor[E[Dependency] <: Event[Dependency]] {
  def execute(dependency: Dependency): Unit
}

但是我不能在execute方法中引用类型参数Dependency - 编译器不知道它。

我知道如果没有HKT,我可以通过以下方式解决它,但这不是这个问题的内容;

trait Actor[T <: Event[Dependency], Dependency] {
   def execute(dependency: Dependency): Unit
}

我想理解为什么它不适用于我尝试过的更高级的kinded类型语法? 是否有可能用HKT表达这一点? 这是HKT的有效用例吗?


编辑

更多信息,事件看起来像这样;

trait Event[Data] {
   val payload: Data
}

......我正在寻找一个像这样的事件和演员;

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

class FooActor extends Actor[FooEvent] {
   def execute(dependency: Foo) = {}
}

我会尽力改善阿列克谢的答案 - 他是对的,但他太矮了。 但我必须说我不是HKT的专家,我想我才刚开始理解这个概念。

在你的代码中, E[Dependency]E[_]相同,后者表示你有一些类型的E作为参数。 这意味着您不会在Dependency操作类型。 您也不能使用EE[Dependency]作为类型。 E是一个类型构造函数,如果我理解正确, E[Dependency]是一个存在类型。 请注意

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

要么

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

也不会编译。

您需要指定正确的类型作为执行的参数:

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

这个将编译为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)

基本上诀窍是定义type P ,它是我们的Dependencytype E = Event[P] ,它总是Event[Dependency]然后你可以通过定义P而不定义E来使用actor,因为它已经定义了。 不确定它是否解决了这个问题,但它看起来像是一种方式去找我。 这里也有太多类型,有些像IntActor是不必要的。 我把它们放在一起,这样就更容易理解这个例子

但是我不能在execute方法中引用类型参数Dependency - 编译器不知道它。

你不能,因为它不是 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 <: Event[Dependency]]选项正是您所需要的。 当你编写Actor[E[Dependency] <: Event[Dependency]] ,这意味着E本身必须有一个类型参数。 并且FooEvent没有,所以Actor[FooEvent]不会编译。

更新2:您可以尝试使用类型成员,如下所示:

trait Event {
  type Dependency
  val payload: Dependency
}

trait Actor {
  type E <: Event

  def execute(e: E#Dependency)
}

class Foo

case class FooEvent(payload: Foo) extends Event {
  type Dependency = Foo
}

class FooActor extends Actor {
  type E = FooEvent

  def execute(e: Foo) = {}
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM