2012-01-15 31 views
2

鉴于一些-kinded更高类型:约束较高kinded类型的功能1的参数和结果类型

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, _]汇编,但我真的很想重新获得一些类型安全。

+0

是否需要是存在的?你能不能仅仅为'declare'添加一个类型参数? – Owen 2012-01-16 09:29:35

+0

我的意思是如果我正确地解释了“某些”的意思,你可以写'(Impl [s] =>事件[s,A]),但我不确定优势已经结束了''''declare'的类型参数。 – Owen 2012-01-16 09:34:35

+0

@Owen是的,它需要这样。 'declare'是从伴侣对象执行的,并声明实现类的事件,而不管用于实例化该类的系统。我只是意识到我的问题是'Function1'的语法 - 所以我添加了一个显示正确语法的答案。 – 2012-01-16 10:23:45

回答

1

这个问题似乎是存在主义的类型不能与“好” Function1语法给出:

// error: not found: type S 
def declare[A](fun: Impl[S] => Event[S, A] forSome { type S }): Key[A] = ??? 

...但它使用正常的语法时,工作原理:

// yes! 
def declare[A](fun: Function1[Impl[S], Event[S, A]] forSome { type S }): Key[A] = ??? 

编辑

不幸的是,现在我的很好的使用网站是拧

missing parameter type for expanded function ((x$1) => x$1.renamed) 
[error] declare[ Renamed ](_.renamed) 

所以我要坚持使用类型不安全版本:-(

我想我会需要像(Impl[S] => Event[S, A]) forAny { type S }一个新的功能...

+1

添加圆括号也使它工作。可能是一个优先问题。 – Owen 2012-01-16 10:34:59

+0

你可以看看http://existentialtype.net/2008/03/09/higher-rank-impredicative-polymorphism-in-scala/。尽管如此,它已经过去了。 – Owen 2012-01-16 10:50:17

相关问题