【发布时间】:2013-09-28 03:09:50
【问题描述】:
给定一些更高种类的类型:
trait Impl [S]
trait Event[S, A]
trait Key [A]
如何重写以下定义:
def declare[A](fun: Impl[_] => Event[_, A]): Key[A] = ???
将fun 参数限制为实际上是Impl[S] => Event[S, A] 对于一些 S。比如下面这种情况:
trait Impl[S] { def ev1: Event[S, Int]; def ev2: Event[T, Int] }
这将是一个有效的调用:
declare(_.ev1)
但这不是:
declare(_.ev2) // this currently compiles
编辑
这里有一个更完整的例子,它准确地说明了我遇到问题的原因:
trait Sys [S <: Sys[S]]
trait Event[S <: Sys[S], A, Repr]
trait Decl {
type Impl[S <: Sys[S]]
protected def declare[U](fun: Impl[_] => Event[_, U, Impl[_]]): Unit = ???
}
以下声明伴随对象的事件编译失败:
object Test extends Decl {
type Impl[S <: Sys[S]] = Test[S]
case class Renamed(name: String)
declare[Renamed](_.renamed)
}
trait Test[S <: Sys[ S]] {
def renamed: Event[S, Test.Renamed, Test[S]]
}
由于一些匹配类型的问题:
error: type mismatch;
found : Event[_$1,Test.Renamed,Test[_$1]] where type _$1
required: Event[_, Test.Renamed, Test.Impl[_]]
Note: _$1 <: Any, but trait Event is invariant in type S.
You may wish to define S as +S instead. (SLS 4.5)
Note: Test[_$1] <: Test[_], but trait Event is invariant in type Repr.
You may wish to define Repr as +Repr instead. (SLS 4.5)
declare[ Renamed ]( _.renamed )
^
如果我将函数类型更改为Impl[_] => Event[_, U, _],它会编译,但我真的很想重新获得一些类型安全性。
【问题讨论】:
-
它需要存在吗?不能只给
declare加一个类型参数吗? -
我的意思是,如果我正确地解释了“对于某些人”的意思,您可以写
(Impl[s] => Event[s,A]) forSome {type s}但我不确定将S设置为 @ 的类型参数有什么好处987654336@. -
@Owen 是的,必须这样。
declare从伴随对象执行并声明实现类的事件,而与用于实例化该类的系统无关。我只是意识到我的问题是Function1的语法——所以我添加了一个显示正确语法的答案。 -
有没有机会你真正寻找的是
Impl[s] => Event[s,A] forAll {type s}(实际上不是有效的scala)? -
@Owen -- 是的,我在一分钟前就意识到了这一点。可惜这不是一个有效的声明......(我会称之为
forAny:) 无论如何谢谢
标签: scala existential-type higher-kinded-types