4

在尝试使用应用程序函子进行验证(Monad 捕获多个异常(不仅仅是单个失败))时,我在 scalaz 中遇到了一个硬限制,它不允许超过 14 个函子,所以这里有一个有用的评论(https://github .com/scalaz/scalaz/issues/504#issuecomment-23626237)引导我使用 HLists 而不是应用函子

现在它工作得非常好(由于它不在 maven https://github.com/typelevel/shapeless-contrib/blob/master/scalaz/main/scala/sequence.scala中,因此必须从这里手动放入这个序列文件之后?来源=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)
    }
  }
4

1 回答 1

7

首先是一个小问题:类型参数 forsuccessNel是错误类型,而不是成功类型,因此它的所有参数都需要相同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手动应用构造函数。

于 2013-09-02T02:03:32.843 回答