将验证从HList应用于案例类

时间:2013-09-02 01:28:09

标签: scala scalaz shapeless hlist

在尝试使用应用程序仿函数(Monad to catch multiple exceptions (not just fail on single))进行验证时,我在scalaz中遇到了一个禁止超过14个仿函数的硬限制,因此这里有一个有用的评论(https://github.com/scalaz/scalaz/issues/504#issuecomment-23626237)导航我使用HLists而不是applicative functor

现在它完全正常(从此处手动输入此序列文件,因为它不在maven https://github.com/typelevel/shapeless-contrib/blob/master/scalaz/main/scala/sequence.scala?source=c

我的问题是,我知道这是可能的,你怎么会自动实例化case class Foo(i:Int,s:String)而不必手动匹配模式与案例,只是再次重新应用参数

基本上我想做这样的事情

  case class Foo(i:Int,s:String)

  implicit def TwoFoo = Iso.hlist(Foo.apply _, Foo.unapply _)

  val someFoo = sequence(
      1.successNel[Int] ::
      "2".successNel[String] ::
      HNil
  ).map { Foo.apply _} // Note this doesn't work

  someFoo match {
    case Success(a) => println(a)
    case Failure(a) => {
      println("failure")
      println(a)
    }
  }

1 个答案:

答案 0 :(得分:7)

首先是一个小问题:successNel的类型参数是错误类型,而不是成功类型,因此它需要在sequence的所有参数中相同。

所以我们可以编写以下内容(假设我们的错误是字符串):

import shapeless._, contrib.scalaz._
import scalaz._, syntax.validation._

case class Foo(i: Int, s: String)

implicit val fooIso = Iso.hlist(Foo.apply _, Foo.unapply _)

val valHList = sequence(1.successNel[String] :: "2".successNel[String] :: HNil)

这为我们提供了Int :: String :: HNil验证。现在我们可以使用我们的同构:

scala> valHList.map(fooIso.from)
res0: scalaz.Validation[scalaz.NonEmptyList[String],Foo] = Success(Foo(1,2))

无需解构列表并手动应用Foo构造函数。