如何在使用scalaz时为布尔创建半群?

时间:2015-12-08 18:17:45

标签: scala scalaz

我使用scalaz进行一些验证,在代码中的某处有布尔条件。样本如下所示:

import scalaz._, std.AllInstances._

object Temporary {

  def validate(x: Int): scalaz.Validation[List[String], Boolean] = {
    try {
      if (x < 10) {
        scalaz.Success(true)
      } else {
        throw new RuntimeException("why oh why")
      }
    } catch {
      case e: Throwable => scalaz.Failure(List(e.getMessage))
    }
  }


  def main(args: Array[String]) {
    val x = validate(1) +++ validate(10)
    println(x)

    val y = List(1,2,4,10).map(validate(_)).reduce(_ +++ _)
    println(y)
  }

}

我遇到了编译错误。

Error:(21, 25) could not find implicit value for parameter M1: scalaz.Semigroup[Boolean]
    val x = validate(1) +++ validate(10)
                        ^

我无法弄清楚如何修复此错误。有什么指针吗?

修改

感谢@Travis Brown的回答,以下是修复此示例的内容。我在对象

中添加了这两行
  import scalaz.Semigroup, scalaz.std.anyVal.booleanInstance.conjunction
  implicit val booleanSemigroup: Semigroup[Boolean] = conjunction

现在它提供了正确的验证:

Failure(List(why oh why))
Failure(List(why oh why))

太酷了!

1 个答案:

答案 0 :(得分:8)

对于布尔运动来说,可以说不是一个独特的半群 - 连词和分离都是追加操作的候选者 - 所以Scalaz没有提供Semigroup[Boolean]。它确实提供了ConjunctionDisjunction标记,如果将标记添加到Boolean值的静态类型(没有运行时开销),则可以获取指定的实例操作:

import scalaz.{ @@, Validation }
import scalaz.Tags.Conjunction

object Temporary {

  def validate(x: Int): Validation[List[String], Boolean @@ Conjunction] = {
    try {
      if (x < 10) {
        scalaz.Success(Conjunction(true))
      } else {
        throw new RuntimeException("why oh why")
      }
    } catch {
      case e: Throwable => scalaz.Failure(List(e.getMessage))
    }
  }

  def main(args: Array[String]) {
    val x = validate(1) +++ validate(10)
    println(x)

    val y = List(1,2,4,10).map(validate(_)).reduce(_ +++ _)
    println(y)
  }
}

如果你真的,真的想选择其中一个操作作为布尔的 半群操作,你可以这样做:

import scalaz.Semigroup, scalaz.std.anyVal.booleanInstance.conjunction

implicit val booleanSemigroup: Semigroup[Boolean] = conjunction

然后:

scala> import scalaz.syntax.semigroup._
import scalaz.syntax.semigroup._

scala> true |+| false
res1: Boolean = false

但这与Scalaz哲学有些不一致。