验证:隐式scalaz.Bind未找到

时间:2014-03-25 12:44:10

标签: validation scala scalaz

我有scalaz验证的这个实现,似乎隐含scalaz.Bind不在范围内,所以表达式不起作用。 这是代码:

import scalaz._
import Scalaz._

case class User(name: String, knowScala: Boolean, age: Int)

object PublicValidationSpec extends BasicValidation {
  def validate(user: User): Validation[String, String] = {
    for {
      b <- checkAge(user)
      c <- checkName(user)
    } yield s"Congrats, ${c.name}"
  }
}

trait BasicValidation {
  def checkName(user: User): Validation[String, User] = {
    if(user.name == "") "must have a name".fail else user.success
  }

  def checkAge(user: User): Validation[String, User] = {
    if(user.age < 3) "must be a valid age".fail else user.success
  }
}

例外是

Error:(14, 25) Implicit not found: scalaz.Unapply[scalaz.Bind, 
scalaz.Validation[String,scalaz.validation.User]]. Unable to unapply type 
`scalaz.Validation[String,scalaz.validation.User]` into a type constructor of 
kind `M[_]` that is classified by the type class `scalaz.Bind`. Check that the 
type class is defined by compiling `implicitly[scalaz.Bind[type constructor]]` and 
review the implicits in object Unapply, which only cover common type 'shapes.'
           b <- checkAge(user)

Did i miss some implicit imports here ?
                        ^

1 个答案:

答案 0 :(得分:6)

验证没有为其定义Bind。

在Scalaz 7.1.0-M5(也是M6)Validation.flatMap已被弃用,并试图破坏警告,看起来flatMap的优先级正在输给scalaz.syntax.bind._,这是Scalaz._导入的一部分。请参阅此提交https://github.com/scalaz/scalaz/commit/2727b2451eba2aa159f3fbb62bf92790ac99dc7a。尝试添加import scalaz.Validation.FlatMap._或仅导入您需要的内容,例如

import scalaz.Validation
import scalaz.syntax.validation._

我建议使用除Validation之外的其他内容,因为这可能会在将来导致更多问题。请参阅下面的scalaz.\/

这可以使用scalaz 7.0.5进行编译。 Validation.flatMap在7.0.6中定义,因此它也应该使用该版本进行编译。我不会在新代码中使用此功能(Validation comprehensions中的for)。

对于Validation.flatMap弃用flatMap已经有一段时间了。 for允许它在Validation.flatMap理解中工作。 flatMap is deprecated in the working branch though。这有很长的背景。见https://groups.google.com/forum/#!topic/scalaz/Wnkdyhebo2w

TLDR - 验证不是monad。 Apply的任何可能实施都不会与为Validation定义的scalaz.\/的行为相匹配。

如果您想在for理解中使用某些内容,请使用Validation(a.k.a。disjunction)。如果您需要累积错误,请使用\/而不是Validation,转换为\/,然后返回{{1}}。