I am using scalaz for some validation, and somewhere in code there are boolean conditions. A sample is shown below:
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)
}
}
I am getting following compilation errors.
Error:(21, 25) could not find implicit value for parameter M1: scalaz.Semigroup[Boolean]
val x = validate(1) +++ validate(10)
^
I cant figure out how to fix this error. Any pointers?
EDIT
Thanks to the answer from @Travis Brown, here is what fixed it for this example. I added these two lines within the object
import scalaz.Semigroup, scalaz.std.anyVal.booleanInstance.conjunction
implicit val booleanSemigroup: Semigroup[Boolean] = conjunction
And now it gives correct validations:
Failure(List(why oh why))
Failure(List(why oh why))
So cool!
There's arguably not a unique semigroup for booleans—both conjunction and disjunction are candidates for the append operation—so Scalaz doesn't provide a Semigroup[Boolean]
. It does provide Conjunction
and Disjunction
tags, and if you add the tag to the static type of your Boolean
values (which has no runtime overhead), you can get an instance for the specified operation:
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)
}
}
If you really, really wanted to pick one of these operations as the semigroup operation for booleans, you could do something like this:
import scalaz.Semigroup, scalaz.std.anyVal.booleanInstance.conjunction
implicit val booleanSemigroup: Semigroup[Boolean] = conjunction
And then:
scala> import scalaz.syntax.semigroup._
import scalaz.syntax.semigroup._
scala> true |+| false
res1: Boolean = false
This is somewhat at odds with the Scalaz philosophy, though.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.