首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >咖喱法中的协变量参数问题

咖喱法中的协变量参数问题
EN

Stack Overflow用户
提问于 2013-04-14 14:40:54
回答 1查看 98关注 0票数 2

对我来说,这是一个相当普遍的情况:

代码语言:javascript
复制
  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)

因此,我有一个协变的东西,我需要先做一些普通的事情,然后有一个通用的部分没有应用。我非常希望能够像上面那样编写它,但这当然会在最后一行产生编译错误:

代码语言:javascript
复制
- type mismatch;  found   : CoVariant[String]  required: CoVariant[Nothing]

我似乎只需要引入一个类,这样就可以将类型参数放在某个地方,这样就可以让它变得抽象起来:

代码语言:javascript
复制
trait StupidWrapper {
   def apply[T](y: CoVariant[T]) : CoVariant[T]
}

而不是咖喱的东西

代码语言:javascript
复制
def notAsNice(x: String) = new StupidWrapper {
   def apply[T](y: CoVariant[T]) = y
}

所以现在:

代码语言:javascript
复制
val applied = notAsNice("foo")
applied(bar)  

编译。

这感觉很蠢,我想还有更好的方法吗?

更新:

我想我最好把它具体化。我所拥有的是:

代码语言:javascript
复制
  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
  }

然后

代码语言:javascript
复制
val thisData = fromTrainingData(trainingLines)
lazy val wordTags = thisData(wordtagParser) // Parser[WordTag]
lazy val uniGrams = thisData(uniGramParser) // Parser[UniGram]
…

我只想废除ParserToSeq,然后做:

代码语言:javascript
复制
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被解决为一个具体的类型,即使类型实际上适用于第二个参数列表。

看来我想在中间的某个地方贴上这类对白的声明:

代码语言:javascript
复制
def fromTrainingData(trainingLines: Seq[String])[T](p: Parser[T])

这当然不是有效的Scala。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-04-14 15:43:17

正如您提到的,scala Function对象don't carry type parameters

但是,您可以将ParseToSeq替换为 that takes higher-kinded types

代码语言:javascript
复制
trait ~>[A[_],B[_]] {
  def apply[X](a : A[X]) : B[X]
}

然后你的例子变成,

代码语言:javascript
复制
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]
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16000251

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档