1

无法理解Semigroupal.product和之间的实际区别Semigroupal.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) 找不到参数 semigroupal 的隐式值:cats.Semigroupal[[+A]cats.data.Validated[Nothing,A]] Semigroupal.tuple2(

看来(如果我没记错的话)Scala 试图找到Monoidto combine Nothing,但不是List[String]. 如何让它工作tuple2

4

1 回答 1

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)
    )
  }
于 2019-03-12T09:13:27.340 回答