首页 文章

Scala更高级的kinded类型语法

提问于
浏览
3

我是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的有效用例吗?


EDIT

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

trait Event[Data] {
   val payload: Data
}

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

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

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

2 回答

  • 2

    我会尽力改善阿列克谢的答案 - 他是对的,但他太矮了 . 但我必须说我不是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] 是此上下文中的类型 .

    Updated:

    请看一下这段代码:

    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 来使用actor,而不定义 E ,因为它已经定义 . 不确定它是否解决了这个问题,但它看起来像是一种方式去找我 . 这里也有太多类型,有些像 IntActor 则没有必要 . 我把它们放在一起,这样就更容易理解这个例子

  • 1

    但是我不能在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) = {}
    }
    

相关问题