带有泛型返回类型的可选函数参数

时间:2010-07-13 15:14:44

标签: scala types

如何实现通过regex解析某些输入并将创建的字符串转换为其他类型的类?我的方法是:

class ARegex[T](regex:Regex, reform:Option[String => T]){
  def findFirst(input:String):Option[T] = {
    (regex.findFirstIn(input), reform) match{
      case (None, _) => None
      case (Some(s), None) => Some(s) // this won't compile because of type mismatch
      case (Some(s), Some(fun)) => Some(fun(s))
    }
  }
}

class BRegex[T](regex:Regex, reform:Option[String => T]) {
  def findFirst(input:String) = {  //returns Option[Any] - erasure
    (regex.findFirstIn(input), reform) match{
      case (None, _) => None
      case (Some(s), None) => Some(s)
      case (Some(s), Some(fun)) => Some(fun(s))
    }
  }
}

3 个答案:

答案 0 :(得分:7)

我们可以通过消除Option类型的reform部分,并使用不同的机制来表明我们不想以任何方式更改匹配来解决此问题。此机制是在您不希望更改类型时使用identity作为默认参数或传递标识。

class ARegex[T](regex:Regex, reform:String => T = identity[String](_)){
  def findFirst(input:String):Option[T] = {
    regex.findFirstIn(input) match{
      case None => None
      case Some(s) => Some(reform(s))
    }
  }
}

new ARegex("something".r).findFirst("something else") //returns Option[String]
new ARegex("3".r, {x=>x.toInt}).findFirst("number 3") //returns Option[Int]

答案 1 :(得分:2)

嗯,问题 类型不匹配,因为您要返回StringT,当然,Any统一了}。您不能说您将返回Option[T]然后返回Option[String]

除此之外,该代码的简化版本如下:

class ARegex[T](regex: Regex, reform: Option[String => T]) {
  def findFirst(input: String): Option[Any] =
    regex findFirstIn input map { s => reform map (_(s)) getOrElse s }
}

但是,您可以返回Option[Either[String, T]]。代码如下所示:

class ARegex[T](regex: Regex, reform: Option[String => T]) {
  def findFirst(input: String): Option[Either[String, T]] =
    regex findFirstIn input map { s => reform map (_(s)) toRight s }
}

答案 2 :(得分:1)

为什么改革选项[String => T]而不仅仅是String => T'如果未传递用于创建所需类型实例的机制,则运行时系统无法实际创建适当的对象。如果你真的需要传入一个Option [String => T]然后你的第二个案子应该只返回无。

另外,flatMap是你的朋友,会给你正确的行为(即如果改革是None,方法返回None。

class RegexExtractor[T](regex: Regex, reform: Option[String => T]) {
  def findFirst(input: String): Option[T] = reform.flatMap(f => regex.findFirstIn(input).map(f))
}