我使用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))
非常酷!
可以说,对于布尔运算来说,并不是一个独特的半群 - 连词和析取都是追加操作的候选者 - 所以Scalaz没有提供Semigroup[Boolean]
.它确实提供Conjunction
和Disjunction
标记,如果将标记添加到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哲学有些不一致.