Thursday 7 June 2012

Okay/Reason extends Checked (a biased scala.Either)

[2012-06-08 Update: added link to 'tests involving Option', demonstrating how 'if' may still be used in for-comprehensions involving Checked.]
[2012-06-09 Update: last four 'tests involving Option' now demonstrate converting from a Checked[A, R] to a Checked[B, R].]
[2012-06-10 Update: the last eight 'tests involving Option' now demonstrate the above; links to Musicians and printMusicians test code added.]

This blog has so far been concerned with how to enhance the existing scala.Either class.

The first three posts presented certain 'extras' that can be used together with the unmodified Either,


while the previous one presented a modified version which claims to fix certain of its shortcomings.

Today's post, however, presents an alternative to Either, and is perhaps the culmination of the above.

Motivation and credits

The current effort is intended to help inform any decision to add an alternative to Either to the Scala library. It owes much to the original author of the Either class, Tony Morris, and to contributors to the debate referred to in the previous post, wherein other alternatives are discussed.

The 'biased alternative' to go alongside the unbiased Either envisaged in that post has now been written. What follows is a brief tutorial, followed by some instructions for using it yourself.

Tutorial

Checked[A, R] is for use as the return type, in place of some type, A, wherever an exception might otherwise be thrown and a more functional style is preferred. Such a result will contain either an A wrapped in an instance of Okay or else an R wrapped in an instance of Reason, depending on whether or not an exceptional condition arose.


Checked vs Either

There are three main differences.

Firstly, rather than have to specify that it's only the value contained in the Right (or perhaps, Left) instance of an Either that's to be passed to the foreach, map or flatMap methods, it is only ever the value contained in Okay instances of Checked, that is passed.


Secondly, Checked has no filter or withFilter method, and consequently, no support for if in for comprehensions, on the grounds that the result should never be empty - either it's Okay, or else there's a Reason why not. Note, however, that if may still be used following a conversion from a Checked to a scala.Option, which does have both these methods, as demonstrated here.

Thirdly, Checked comes complete with implicit support similar to that provided for Either by EitherExtras:
  • a.succeed becomes a.toOkay
  • a.fail    becomes a.toReason
  • a.fastCheck becomes a.ff (as in fail-fast)
  • a.slowCheck becomes a.fs (as in fail-slowly)
  • fast(f) <*> ... becomes ff(f) <*> ... where f is curried
  • slow(f) <*> ... becomes fs(f) <*> ... ditto

Mix-in or import

Checked, together with its implicit support, is nested in a trait called Checking. As is the case for EitherExtras, this has an abstract type, now called R, which must be set to the type of the value wrapped by Reason when using the <*> operator.

As is also the case for EitherExtras, Checking has a companion object which extends its companion trait, and sets the abstract type to String.

For example code, please see the following test code:

Instructions

To make use of the Scala 2.9.2-compatible class files now available in the Maven central repository, add the following to your build.sbt,

libraryDependencies += "org.lafros" %% "scala-checking" % "1.0"

or the following to your pom.xml.
<dependency>
  <groupId>org.lafros</groupId>
  <artifactId>scala-checking</artifactId>
  <version>1.0</version>
</dependency>
The code is available under the Apache v2.0 licence, and maintained in a Github project called scala-checking.

Comments welcome.


No comments:

Post a Comment