外部系统返回Seq [String](类型为DB,输出类似于CSV / json),它是基类型的换行:string / numbers。我宁愿使用自己的模型。
object Converter {
type Output = (Int, String, Double) // for instance
def convert(values: List[String]): Output
}
显然,我不想每次都实现convert-method。
似乎我需要比这更简单的东西 http://nrinaudo.github.io/tabulate/tut/parsing.html
可以在这里使用HList吗?就像通过定义仅显式输出类型将HList(String :: String :: String :: HNil)转换为模型一样。
答案 0 :(得分:3)
首先,convert
方法的输出必须为Option[Output]
,或Output
的一些monad(Try
,Either
,{{ 1}},scalaz.\/
等)如果scalaz.Validation
的内容无法转换为Seq[String]
(错误的Output
长度,则解析错误{{} 1}} s或Seq
等。)
使用Int
的可能实现具有将Doubles
转换为其参数类型的类型类,以及用于将shapeless
String
转换为HList
的辅助类型类1}} String
与第一个类型类的表示。
以下是一个示例实现:
HList
升级此实现以返回您选择的错误monad(或抛出异常)而不是返回Output
以下是您可以使用它的方法:
import shapeless._
import shapeless.syntax.std.traversable._
import shapeless.ops.traversable._
trait Parse[Out] {
def apply(value: String): Option[Out]
}
object Parse {
implicit object convertToInt extends Parse[Int] {
def apply(value: String) = Try(value.toInt).toOption
}
implicit object convertToString extends Parse[String] {
def apply(value: String) = Some(value)
}
implicit object convertToDouble extends Parse[Double] {
def apply(value: String) = Try(value.toDouble).toOption
}
}
trait ParseAll[Out] {
type In <: HList
def apply(values: In): Option[Out]
}
object ParseAll {
type Aux[I, O] = ParseAll[O] { type In = I }
implicit object convertHNil extends ParseAll[HNil] {
type In = HNil
def apply(value: HNil) = Some(HNil)
}
implicit def convertHList[T, HO <: HList](implicit
cv: Parse[T],
cl: ParseAll[HO]
) = new ParseAll[T :: HO] {
type In = String :: cl.In
def apply(value: In) = value match {
case x :: xs => for {
t <- cv(x)
h0 <- cl(xs)
} yield t :: h0
}
}
}
trait Converter {
type Output
def convert[S <: HList, H <: HList](values: List[String])(implicit
gen: Generic.Aux[Output, H], // Compute HList representation `H` of Output
parse: ParseAll.Aux[S, H], // Generate parser of Hlist of String `S` to HList `H`
ft: FromTraversable[S] // Generate converter of `List[String]` to HList of Strings `S`
): Option[Output] =
values.toHList[S].flatMap(parse.apply).map(gen.from)
}
它也适用于案例类而不是元组:
Option