Skip to content

Instantly share code, notes, and snippets.

@bvenners
Created November 5, 2014 08:12
Show Gist options
  • Save bvenners/b129cccf6d6486316030 to your computer and use it in GitHub Desktop.
Save bvenners/b129cccf6d6486316030 to your computer and use it in GitHub Desktop.
Example showing Scalactic's Validation used to accumulate errors with the "when" combinator
scala> import org.scalactic._
import org.scalactic._
// A Validation is either a Pass or a Fail. A Validation is like an
// Option with the reverse attitude: Pass is like None, it contains no
// value and just means the value being validated is OK as is. Fail is
// like Some, it holds an error value describing the validation failure.
scala> def isPositive(i: Int): Validation[ErrorMessage] =
| if (i > 0) Pass else Fail(s"$i was not positive")
isPositive: (i: Int)org.scalactic.Validation[org.scalactic.ErrorMessage]
scala> isPositive(3)
res0: org.scalactic.Validation[org.scalactic.ErrorMessage] = Pass
scala> isPositive(-3)
res1: org.scalactic.Validation[org.scalactic.ErrorMessage] = Fail(-3 was not positive)
// Validations can be used with when to accumulate errors (including in for expressions)
scala> def parseInt(input: String): Int Or One[ErrorMessage] = {
| try Good(input.trim.toInt)
| catch {
| case _: NumberFormatException => Bad(One(s"$input was not an integer"))
| }
| }
parseInt: (input: String)org.scalactic.Or[Int,org.scalactic.One[org.scalactic.ErrorMessage]]
scala> import Accumulation._
import Accumulation._
scala> parseInt("three") when isPositive
res2: org.scalactic.Or[Int,org.scalactic.Every[org.scalactic.ErrorMessage]] = Bad(One(three was not an integer))
scala> parseInt("3") when isPositive
res3: org.scalactic.Or[Int,org.scalactic.Every[org.scalactic.ErrorMessage]] = Good(3)
scala> parseInt("-3") when isPositive
res4: org.scalactic.Or[Int,org.scalactic.Every[org.scalactic.ErrorMessage]] = Bad(One(-3 was not positive))
// You can use when to accumulate errors from multiple validations
scala> def isRound(i: Int): Validation[ErrorMessage] =
| if (i % 10 == 0) Pass else Fail(s"$i was not evenly divisible by 10")
isRound: (i: Int)org.scalactic.Validation[org.scalactic.ErrorMessage]
// "30" passes both isPositive and isRound validations
scala> parseInt("30") when (isPositive, isRound)
res5: org.scalactic.Or[Int,org.scalactic.Every[org.scalactic.ErrorMessage]] = Good(30)
// "3" fails the isRound validation
scala> parseInt("3") when (isPositive, isRound)
res6: org.scalactic.Or[Int,org.scalactic.Every[org.scalactic.ErrorMessage]] = Bad(One(3 was not evenly divisible by 10))
// "-30" fails the isPositive validation
scala> parseInt("-30") when (isPositive, isRound)
res7: org.scalactic.Or[Int,org.scalactic.Every[org.scalactic.ErrorMessage]] = Bad(One(-30 was not positive))
// "-3" fails both validations, so two error messages appear in the result
scala> parseInt("-3") when (isPositive, isRound)
res8: org.scalactic.Or[Int,org.scalactic.Every[org.scalactic.ErrorMessage]] =
Bad(Many(-3 was not positive, -3 was not evenly divisible by 10))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment