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

Need to make a quick json fixes – JSONPath for rescue

From time to time I have a need to do some fixes in my json data. In a world of flat files I do this with grep/sed/awk tool chain. How to handle it for JSON? Searching for a solution I came across the JSONPath. It quite mature tool (from 2007) but I haven't hear about it so I decided to share my experience with others.

First of all you can try it without pain online: http://jsonpath.curiousconcept.com/. Full syntax is described at http://goessner.net/articles/JsonPath/



But also you can download python binding and run it from command line:
$ sudo apt-get install python-jsonpath-rw
$ sudo apt-get install python-setuptools
$ sudo easy_install -U jsonpath

After that you can use inside python or with simple cli wrapper:
#!/usr/bin/python
import sys, json, jsonpath

path = sys.argv[
1]

result = jsonpath.jsonpath(json.load(sys.stdin), path)
print json.dumps(result, indent=2)

… you can use it in your shell e.g. for json:
{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}

You can print only book nodes with price lower than 10 by:
$ jsonpath '$..book[?(@.price 

Result:
[
{
"category": "reference",
"price": 8.95,
"title": "Sayings of the Century",
"author": "Nigel Rees"
},
{
"category": "fiction",
"price": 8.99,
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"author": "Herman Melville"
}
]

Have a nice JSON hacking!From time to time I have a need to do some fixes in my json data. In a world of flat files I do this with grep/sed/awk tool chain. How to handle it for JSON? Searching for a solution I came across the JSONPath. It quite mature tool (from 2007) but I haven't hear about it so I decided to share my experience with others.