将 List[String] 解析为 HList [英] Parse List[String] into HList

查看:39
本文介绍了将 List[String] 解析为 HList的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想写def parse[T <: HList](list: List[String]): Validation[T].list 可以是 List("fooid", "barid")T FooId :: BarId :: HNil,以及一个实现 String => 的类型类 Parse[T]验证[FooId].我将如何编写将列表解析为 Tparse?我不确定如何为 T 的每个元素调用隐式类型类.

I would like to write def parse[T <: HList](list: List[String]): Validation[T]. list could be List("fooid", "barid"), and T FooId :: BarId :: HNil, and a typeclass Parse[T] which implements String => Validation[FooId]. How would I write said parse, which parses the list into T? I'm not sure how to summon the implicit typeclasses for each of the elements of T.

推荐答案

我们可以修改 shapeless.ops.traversable.FromTraversable.

We can adapt the code from shapeless.ops.traversable.FromTraversable.

我不确定您的 Validation 类型是什么,但我将它用作下面 scalaz.ValidationNel[String, A] 的别名(主要是这样我可以使用 string 语法可以轻松地给我一些 Parse 实例).

I'm not sure what your Validation type is, but I used it as an alias for scalaz.ValidationNel[String, A] below (mostly so I could use the string syntax to easily give me some Parse instances).

import scalaz.{Validation => _, _}, Scalaz._

type Validation[A] = ValidationNel[String, A]

trait Parse[T] {
  def apply(s: String): Validation[T]
}

object Parse {
  def fromScalazParse[E <: Exception, T](f: String => scalaz.Validation[E, T]) =
    new Parse[T] {
      def apply(s: String): Validation[T] =
        f(s).leftMap(_.getMessage).toValidationNel
    }

  implicit val booleanParse = fromScalazParse(_.parseBoolean)
  implicit val intParse     = fromScalazParse(_.parseInt)
  implicit val doubleParse  = fromScalazParse(_.parseDouble)
}

随着 Parser 类型类的排序,我们现在可以创建一个基于 FromTraversable 的类型类来解析一个 List[String] 并给出我们一个 Validation[A :: B :: HNil] :

With the Parser type class sorted, we can now create a type class based on FromTraversable to parse a List[String] and give us a Validation[A :: B :: HNil] :

import shapeless._
import scala.collection.GenTraversable

trait FromTraversableParsed[Out <: HList] extends Serializable {
  def apply(l: GenTraversable[String]) : Validation[Out]
}

object FromTraversableParsed {
  def apply[Out <: HList](implicit from: FromTraversableParsed[Out]) = from

  implicit val hnilFromTraversableParsed = 
    new FromTraversableParsed[HNil] {
      def apply(l: GenTraversable[String]): Validation[HNil] =
        if(l.isEmpty) HNil.successNel[String]
        else "Traversable is not empty".failureNel[HNil]
    }

  implicit def hlistFromTraversableParsed[OutH, OutT <: HList](implicit 
    ftpT: FromTraversableParsed[OutT],
    parseH: Parse[OutH]
  ): FromTraversableParsed[OutH :: OutT] = 
    new FromTraversableParsed[OutH :: OutT] {
      def apply(l : GenTraversable[String]) : Validation[OutH :: OutT] =
        if(l.isEmpty) "Empty traversable".failureNel[OutH :: OutT]
        else (parseH(l.head) |@| ftpT(l.tail))(_ :: _)
    }
}

我们可以添加一些语法来使 FromTraversableParsed 的使用更容易一些:

We can add some syntax to make using FromTraversableParsed a little bit easier :

implicit class ParseStringListOps(val strings: List[String]) extends AnyVal {
  def parse[L <: HList](implicit ftp: FromTraversableParsed[L]): Validation[L] =
    ftp(strings)
}

现在我们可以:

List("1", "true", "3.0").parse[Int :: Boolean :: Double :: HNil]
// Validation[Int :: Boolean :: Double :: HNil] = Success(1 :: true :: 3.0 :: HNil)

这篇关于将 List[String] 解析为 HList的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆