这对我来说开始成为一种很常见的情况:
trait CoVariant[+T] {
def bar: T
}
def curried[T](x: String)(y: CoVariant[T]) = y // Not really, but for simplicity
val applied = curried("foo") _
val bar = new CoVariant[String] {
def bar = "bar"
}
applied(bar)
所以我有一些协变的东西,我需要先做一些常见的事情,然后有一个通用部分未应用。我真的希望能够像上面这样的柯里化(Currying)函数一样编写它,但这当然会在最后一行产生编译错误:
- type mismatch; found : CoVariant[String] required: CoVariant[Nothing]
我似乎只是引入一个类,只是为了有地方可以粘贴类型参数,这样它就可以保持抽象:
trait StupidWrapper {
def apply[T](y: CoVariant[T]) : CoVariant[T]
}
而不是 curry 的东西
def notAsNice(x: String) = new StupidWrapper {
def apply[T](y: CoVariant[T]) = y
}
现在:
val applied = notAsNice("foo")
applied(bar)
编译。
这感觉很愚蠢,我想还有更好的方法吗?
更新:
我想我会更好地具体化。我所拥有的是这样的:
abstract class ParserToSeq {
def apply[T](parser: Parser[T]): Seq[T]
}
def fromTrainingData(trainingLines: Seq[String]) = new ParserToSeq {
def apply[T](p: Parser[T]) = trainingLines.map(parseAll(p, _)).map {
_ match {
case Success(wt, _) => Some(wt)
case _ => None
}
}.flatten
}
然后
val thisData = fromTrainingData(trainingLines)
lazy val wordTags = thisData(wordtagParser) // Parser[WordTag]
lazy val uniGrams = thisData(uniGramParser) // Parser[UniGram]
…
我只想取消 ParserToSeq 并执行以下操作:
def fromTrainingData[T](trainingLines: Seq[String])(p: Parser[T]) =
trainingLines.map(parseAll(p, _)).map {
_ match {
case Success(wt, _) => Some(wt)
case _ => None
}
}.flatten
请注意,此处的 T 特定于每个解析器。据我了解,问题是 T 被解析为部分应用方法上的具体类型,即使该类型实际上适用于第二个参数列表。
看来我想将类型参数的声明放在中间的某个地方:
def fromTrainingData(trainingLines: Seq[String])[T](p: Parser[T])
这当然不是有效的 Scala。
最佳答案
正如你提到的,scala Function
对象 don't carry type parameters .
但是,您可以将 ParseToSeq
替换为 more generic ~>
that takes higher-kinded types ,
trait ~>[A[_],B[_]] {
def apply[X](a : A[X]) : B[X]
}
那么你的例子就变成了,
trait Parser[T]
trait WordTag
trait UniGram
val trainingLines: Seq[String] = ???
val wordtagParser: Parser[WordTag] = ???
val uniGramParser: Parser[UniGram] = ???
def fromTrainingData[T](trainingLines: Seq[String]) = new ~>[Parser,Seq] {
def apply[T](p: Parser[T]): Seq[T] = ???
}
val thisData = fromTrainingData(trainingLines)
lazy val wordTags = thisData(wordtagParser) // Seq[WordTag]
lazy val uniGrams = thisData(uniGramParser) // Seq[UniGram]
关于scala - 柯里化(Currying)方法最后出现协变参数问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16000251/