使用Scala中Cats库中的Validated

时间:2019-03-11 14:22:36

标签: scala validation scala-cats semigroup

无法理解Semigroupal.productSemigroupal.tuple2之间的实际差异。这是一个简短的示例:

import cats.Semigroupal
import cats.data.Validated
import cats.data.Validated.Invalid
import cats.instances.list._ // for Monoid

  type AllErrorsOr[A] = Validated[List[String], A]
  def bothInvalid = {
    Semigroupal[AllErrorsOr].product(
      Validated.invalid(List("Error 1")),
      Validated.invalid(List("Error 2"))
    )
  }

  def bothInvalidTuple = {
    Semigroupal.tuple2(
      Validated.invalid(List("Error 1")),
      Validated.invalid(List("Error 2"))
    )
  }

  def bothValid = {
    Semigroupal[AllErrorsOr].product(
      Validated.valid(10),
      Validated.valid(20)
    )
  }

  def bothValidTuple = {
    Semigroupal.tuple2(
      Validated.valid(10),
      Validated.valid(20)
    )
  }

对于无效,bothInvalidbothInvalidTuple给出相同的结果。使用有效值,仅编译第一个。我收到的错误:

  

错误:(40,23)找不到参数的隐式值   半组:cats.Semigroupal [[+ A] cats.data.Validated [Nothing,A]]       Semigroupal.tuple2(

(如果我没记错的话)Scala试图找到Monoid来合并Nothing,而不是List[String]。如何使其与tuple2一起使用?

1 个答案:

答案 0 :(得分:1)

只是一些泛型没有被推断出来。尝试明确指定它们

  type AllErrorsOr[A] = Validated[List[String], A]

  def bothInvalid: AllErrorsOr[(Int, Int)] = {
    Semigroupal[AllErrorsOr].product[Int, Int](
      Validated.invalid(List("Error 1")),
      Validated.invalid(List("Error 2"))
    )
  }

  def bothInvalidTuple: AllErrorsOr[(Int, Int)] = {
    Semigroupal.tuple2[AllErrorsOr, Int, Int](
      Validated.invalid(List("Error 1")),
      Validated.invalid(List("Error 2"))
    )
  }

  def bothValid: AllErrorsOr[(Int, Int)] = {
    Semigroupal[AllErrorsOr].product[Int, Int](
      Validated.valid(10),
      Validated.valid(20)
    )
  }

  def bothValidTuple: AllErrorsOr[(Int, Int)] = {
    Semigroupal.tuple2[AllErrorsOr, Int, Int](
      Validated.valid(10),
      Validated.valid(20)
    )
  }