【问题标题】:Problems with covariant parameters last in curried method柯里化方法中协变参数的问题
【发布时间】:2013-04-14 14:40:54
【问题描述】:

这对我来说开始很常见:

  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)

所以我有一些共同变体的东西,我需要先做一些常见的东西,然后让一个通用的部分不应用。我真的很希望能够像上面的柯里化函数一样编写它,但这当然会在最后一行产生编译错误:

- type mismatch;  found   : CoVariant[String]  required: CoVariant[Nothing]

我似乎诉诸于引入一个类,只是为了在某个地方粘贴类型参数,以便将其保留为抽象:

trait StupidWrapper {
   def apply[T](y: CoVariant[T]) : CoVariant[T]
}

而不是咖喱的东西有

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 currying variance


    【解决方案1】:

    正如你提到的,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]
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-01
    • 1970-01-01
    • 2011-05-26
    • 2011-08-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多