Validation with warnings in scala with scalaz

Monad are containers with ‘special powers’, when it comes to applying function over its content.Validation special power is propagating Failure over validation process.If you are not familiar with scalaz.Validation I urge you to read this example,…

Monad are containers with ‘special powers’, when it comes to applying function over its content.
Validation special power is propagating Failure over validation process.

If you are not familiar with scalaz.Validation I urge you to read this example, which shows how to use Validation: A Tale of 3 Nightclubs

Basically validation looks like this:

Scalaz.Validation uses idiomatic scala way to compose monads by For Comprehension.

Concrete validation method, returning scalaz.Validation instances looks like this:

Scalaz provide helper methods for wrapping values into Failure or Success.

To sum it up. Validation is a an elegant way to handle application validation logic.

However it’s not enough.

Our business rules require application logic’s to perform validation with warnings, which should not propagate as failures, but rather propagate independently of Success/Failure types.

We liked monad approach to data validation so we wanted to keep it that way.

Let me introduce Validation with warnings

What it does is basically wrapping scalaz.Validation into another type responsible for carrying warnings over validation process

Thank to scala type inference our validation code look’s just the same, but now for expression operates on ValidationWithWarnings type rather than Validation.

OK, but what about validation code? We created similar helper methods for wrapping validation into ValidationWithWarnings and wrapping values directly into warnings.

One could inline warning in for loop:

Or use it in validation method:

And of course chain it in for-loop:

Applicative

We support scalaz.Applicative, so it’s possible to take few validations and apply them to function if all elements are successes, collecting any errors and warnings if present.

Summing

Similarly to scalaz.Validation, we also support summing values, if value type has Semigroup typeclass:

Repository

Code with examples in test files can be found at https://github.com/Ajk4/ValidationWithWarnings

Q&A

Why not use Writer Monad?
– Same reason why we prefer Validation over Either with left/right projection. It’s more direct and descriptive.

Why validation nel underhood?
– It suited our business needs best.

Validation is not a Monad!
– True. 

You May Also Like

EhCache config with BeanUtils

BeanUtils allows you to set Bean properties.If you have configuration stored in a Map it's tempting to use BeanUtils to automagically setup EhCache configuration.Sadly this class has mixed types in setters and getter and thus BeanUtils that use Introsp...

Private fields and methods are not private in groovy

I used to code in Java before I met groovy. Like most of you, groovy attracted me with many enhancements. This was to my surprise to discover that method visibility in groovy is handled different than Java!

Consider this example:

class Person {
private String name
public String surname

private Person() {}

private String signature() { "${name?.substring(0, 1)}. $surname" }

public String toString() { "I am $name $surname" }
}

How is this class interpreted with Java?

  1. Person has private constructor that cannot be accessed
  2. Field "name" is private and cannot be accessed
  3. Method signature() is private and cannot be accessed

Let's see how groovy interpretes Person:

public static void main(String[] args) {
def person = new Person() // constructor is private - compilation error in Java
println(person.toString())

person.@name = 'Mike' // access name field directly - compilation error in Java
println(person.toString())

person.name = 'John' // there is a setter generated by groovy
println(person.toString())

person.@surname = 'Foo' // access surname field directly
println(person.toString())

person.surname = 'Bar' // access auto-generated setter
println(person.toString())

println(person.signature()) // call private method - compilation error in Java
}

I was really astonished by its output:

I am null null
I am Mike null
I am John null
I am John Foo
I am John Bar
J. Bar

As you can see, groovy does not follow visibility directives at all! It treats them as non-existing. Code compiles and executes fine. It's contrary to Java. In Java this code has several errors, pointed out in comments.

I've searched a bit on this topic and it seems that this behaviour is known since version 1.1 and there is a bug report on that: http://jira.codehaus.org/browse/GROOVY-1875. It is not resolved even with groovy 2 release. As Tim Yates mentioned in this Stackoverflow question: "It's not clear if it is a bug or by design". Groovy treats visibility keywords as a hint for a programmer.

I need to keep that lesson in mind next time I want to make some field or method private!