簡體   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