在Scala中为元组键入类组合?
我试图实现一个更为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
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: