Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Scala中为元组键入类组合?_Scala_Typeclass - Fatal编程技术网

在Scala中为元组键入类组合?

在Scala中为元组键入类组合?,scala,typeclass,Scala,Typeclass,我试图实现一个更为Scala友好的java.util.Scanner版本,例如,我希望它能够解析任何定义了解析器的类型类,而不是Scanner.nextInt()。以下是我尝试的要点: import java.io.{BufferedReader, Reader, InputStreamReader, StringReader, InputStream} import java.util.StringTokenizer class InputReader(reader: BufferedRea

我试图实现一个更为Scala友好的
java.util.Scanner
版本,例如,我希望它能够解析任何定义了解析器的类型类,而不是
Scanner.nextInt()
。以下是我尝试的要点:

import java.io.{BufferedReader, Reader, InputStreamReader, StringReader, InputStream}
import java.util.StringTokenizer

class InputReader(reader: BufferedReader) extends Iterator[String] with AutoCloseable {
  def this(reader: Reader) = this(new BufferedReader(reader))
  def this(inputStream: InputStream) = this(new InputStreamReader(inputStream))
  def this(str: String) = this(new StringReader(str))

  private[this] val tokenizers = Iterator.continually(reader.readLine()).takeWhile(_ != null).map(new StringTokenizer(_)).buffered

  @inline private[this] def tokenizer(): Option[StringTokenizer] = {
    while(tokenizers.nonEmpty && !tokenizers.head.hasMoreTokens) tokenizers.next()
    if (tokenizers.nonEmpty) Some(tokenizers.head) else None
  }

  def read[A: Parser]: A = implicitly[Parser[A]].apply(next())

  def tillEndOfLine(): String = tokenizer().get.nextToken("\n\r")
  override def next() = tokenizer().get.nextToken()
  override def hasNext = tokenizer().nonEmpty
  override def close() = reader.close()
}

trait Parser[A] {
  def apply(s: String): A
}
object Parser {
  def apply[A](f: String => A) = new Parser[A] {
    override def apply(s: String) = f(s)
  }
  implicit val stringParser: Parser[String] = Parser(identity)
  implicit val charParser: Parser[Char] = Parser(s => s.ensuring(_.length == 1, s"Expected Char; found $s").head)
  implicit val booleanParser: Parser[Boolean] = Parser(_.toBoolean)
  implicit val intParser: Parser[Int] = Parser(_.toInt)
  implicit val longParser: Parser[Long] = Parser(_.toLong)
  implicit val bigIntParser: Parser[BigInt] = Parser(BigInt(_))
  implicit val doubleParser: Parser[Double] = Parser(_.toDouble)
  implicit val bigDecimalParser: Parser[BigDecimal] = Parser(BigDecimal(_))
}
这使得可以定义自定义解析器并用作:

val reader = new InputReader(System.in)
reader.read[Int]
reader.read[String]
但是,现在,既然我知道如何读取
Int
String
,我该如何读取
reader.read[(Int,String)]

这是我的尝试

首先,我将
解析器
类型类更改为接受
输入读取器
本身:

trait Parser[A] {
  def apply(context: InputReader): A
}
object Parser {
  def apply[A](f: String => A) = new Parser[A] {
    override def apply(context: InputReader) = f(context.next())
  }
}
然后,我为
Tuple2
定义了一个
解析器

implicit def tupleParser[A: Parser, B: Parser]: Parser[(A, B)] = new Parser[(A, B)] {
  override def apply(context: InputReader) = implicitly[Parser[A]].apply(context) -> implicitly[Parser[B]].apply(context)
}

这让我调用
reader.read[(Int,String)]
。但这是难以置信的冗长,因为我现在必须为所有n元组定义解析器。有更好的方法吗?

为什么不使用Scala?@cchantep:这是用于消费非结构化输入的,例如@cchantep:我刚才只是在证明这是一个示例。一般来说,我对为元素具有类型类的元组生成类型类的策略感兴趣……您可以看看Shapeless: