0%

In this post we’ll look at NonEmptyList which is a singly-linked list guaranteed to be non-empty. Let’s begin by seeing how using a NEL (short for NonEmptyList) in appropriate places is better than using regular List.

Contrasting List with NEL

1
2
3
4
@ def email(body: String, recipients: List[String]): Unit = {
// send email
}
defined function email

Let’s say we’re writing an email function that sends email to a list of people. A naive assumption would be to always expect recipients to have at least one element. However, we may end up with an empty list and that’ll lead to painstaking debugging trying to find out why emails weren’t sent out.

So, we’ll change our email function to this:

1
2
3
4
5
6
7
8
@ def email(body: String, recipients: List[String]): Either[String, String] = {
if(recipients.length == 0)
Left("Empty list of recipients")
else
// send email
Right(s"Email sent to ${recipients.length} recipient(s)")
}
defined function email

Now although we’re handling the case of empty list, we’ve introduced unnecessary noise with an if-else. Here’s how we can get a guarantee on being non-empty and avoid the conditional:

1
2
3
4
5
6
7
8
@ import scalaz._
import scalaz._
@ import Scalaz._
import Scalaz._
@ def email(body: String, recipients: NonEmptyList[String]): Unit = {
// send email
}
defined function email

Voila! Using a NEL gives us two advantages:

  • A guarantee on never receiving an empty list
  • Expressing our intent in the function signature

With that said, let’s look at how we can create and use NELs.

Creating a NEL

1
2
@ NonEmptyList(1, 2, 3, 4)
res2: NonEmptyList[Int] = NonEmpty[1,2,3,4]

In the example above, we’re using the apply method to create a NEL. It looks like the following:

1
def apply[A](h: A, t: A*)

The first argument is the head whereas the second argument is varargs which becomes the tail. Internally, the apply method calls the nels method. We can use that directly, too.

1
2
@ NonEmptyList nels(1, 2, 3, 4)
res3: NonEmptyList[Int] = NonEmpty[1,2,3,4]

You can also create a NEL from a single value by using wrapNel.

1
2
@ 1.wrapNel
res4: NonEmptyList[Int] = NonEmpty[1]

You can even create a NEL in the cons list way like you’d do with a List

1
2
3
4
5
6
7
// good ol' List
@ 1 :: List(2, 3, 4)
res5: List[Int] = List(1, 2, 3, 4)

// NEL
@ 1 <:: NonEmptyList(2, 3, 4)
res6: NonEmptyList[Int] = NonEmpty[1,2,3,4]

You can convert a List to a NEL by calling toNel. This will yield an Option of NEL since the List may be empty

1
2
@ List(1, 2, 3) toNel
res7: Option[NonEmptyList[Int]] = Some(NonEmpty[1,2,3])

Appending NELs

1
2
@ NonEmptyList(1, 2, 3) append NonEmptyList(4, 5, 6)
res8: NonEmptyList[Int] = NonEmpty[1,2,3,4,5,6]

You can also concatenate two NELs by using append.

Head and Tail

1
2
3
4
5
6
7
8
9
10
11
@ NonEmptyList(1, 2, 3).head
res13: Int = 1
@ NonEmptyList(1, 2, 3).tail
res14: IList[Int] = ICons(2, ICons(3, []))

@ List().head
java.util.NoSuchElementException: head of empty list
scala.collection.immutable.Nil$.head(List.scala:428)
scala.collection.immutable.Nil$.head(List.scala:425)
ammonite.$sess.cmd15$.<init>(cmd15.sc:1)
ammonite.$sess.cmd15$.<clinit>(cmd15.sc)

head and tail return and head and tail of the NEL, respectively. Note that head is guaranteed to work without exceptions because we’ll always have one element.

Iterating

1
2
3
4
5
6
7
@ NonEmptyList(1, 2, 3) foreach println
1
2
3

@ NonEmptyList(1, 2, 3) map { _ + 1 }
res18: NonEmptyList[Int] = NonEmpty[2,3,4]

Because NEL is also a list, you can perform familiar list operations like foreach, map, etc.

Conclusion

This post was intended to give you an introduction to Scalaz NonEmptyList and how it differs from the usual List. The guarantee on NEL being non-empty means that you can call head without having to worry about exceptions. This makes your code less cluttered and its intent more expressive.

In this post we’ll look at Scalaz Either. This is Scalaz’s version of the standard Scala Either. Before we look at Scalaz Either, we’ll look at Scala Either.

Scala Either

Let’s begin by going over the docs:[1]

Represents a value of one of two possible types (a disjoint union.) Instances of Either are either an instance of Left or Right.

Convention dictates that Left is used for failure and Right is used for success.

With the definition out of the way, let’s look at some code. The example is modeled around the code in the official Scala Either docs.

Creating an Either

1
2
3
4
5
6
7
8
@ def parseInt(str: String): Either[String, Int] = {
try {
Right(str toInt)
} catch {
case e: Exception => Left(e getMessage)
}
}
defined function parseInt

Next, let’s create a case each of success and failure.

1
2
3
4
@ val success = parseInt("2")
success: Either[String, Int] = Right(2)
@ val failure = parseInt("apple")
failure: Either[String, Int] = Left("For input string: \"apple\"")

Using a for Comprehension

Scala Either is not a monad and so you cannot use it in a for comprehensions.

1
2
3
4
@ for {
n <- success
} yield n
res3: Either[String, Int] = Right(2)


NOTE:

Previously, Scala Either was not a monad so it couldn’t be used in for comprehensions. Now, it is a monad and can be used in for comprehensions.


Scalaz Either

A valid question to ask is why would one use Scalaz Either when Scala Either is a monad. The answer is that Scalaz Either is a lot more convenient and powerful compared to Scala Either. Let’s begin by refactoring parseInt to return a Scalaz Either.

Creating an Either

1
2
3
4
5
6
7
8
9
10
11
12
@ import scalaz._
import scalaz._
@ import Scalaz._
import Scalaz._
@ def parseInt(str: String): String \/ Int = {
import scala.util.{Try, Success, Failure}
Try { str toInt } match {
case Success(n) => n.right[String]
case Failure(e) => e.getMessage.left[Int]
}
}
defined function parseInt

Next, let’s create a case each of success and failure.

1
2
3
4
@ val success = parseInt("2")
success: String \/ Int = \/-(2)
@ val failure = parseInt("apple")
failure: String \/ Int = -\/("For input string: \"apple\"")

The return type of our function is indicated by String \/ Int. This means we may return a String on the left in case of failure and an Int on the right in case of success. We create right or left projections by calling right or left, respectively, and mentioning the type of the value that will be on the other side. For example, we call right[String] because the left side is a String. The right projection is indicated by \/- and left projection is indicated by -\/.

Using a for Comprehension

1
2
3
4
@ for {
n <- success
} yield n
res12: String \/ Int = \/-(2)

Because Scalaz Either is also a monad, it can be used in a for comprehension.

Checking Left or Right

1
2
3
4
@ success isRight
res13: Boolean = true
@ failure isLeft
res14: Boolean = true

Akin to Scala Either, Scalaz Either also lets you check for left or right by calling isLeft or isRight, respectively.

Ternary Operator

1
2
@ success ? "YES" | "NO"
res15: String = "YES"

Scalaz Either provides you with a getOrElse which you can use to as a ternary operator using its symbolic representation |.

Folding an Either

1
2
3
4
5
6
7
8
9
10
@ success fold(
left => -1,
right => right + 1
)
res16: Int = 3
@ failure fold(
left => -1,
right => right + 1
)
res17: Int = -1

Both Scala and Scalaz Either provide you with a fold method which run the first function if we have a left, or the second function if we have a right.

Converting to Validation

The single biggest difference between Scala Either and Scalaz Either is that Scalaz Either can be converted to other types like Validation, etc. For example, converting an Either to a Validation allows you to accumulate errors. As the code comments state:

A \/ B is also isomorphic to Validation[A, B]. The subtle but important difference is that Applicative instances for Validation accumulates errors (“lefts”)

1
2
@ 1.right validation
res65: Validation[Nothing, Int] = Success(1)

We create a Validation by calling validation method on the Either instance. Depending on a left or right, we get either a Success or Failure.

Conclusion

Scalaz Either and Scala Either are pretty similar in the latest version of Scala (2.12, as of writing). Which one you decide to use depends upon your personal preference. My preference is to use Scalaz Either throughout my code if I am using other Scalaz features to maintain consistency.

Introduction

In this post we’ll look at Scalaz Validation which you can use to validate the data in your system. Data validation is a part and parcel of software development; you have to check the data that comes into your system or it may lead to unexpected behavior and / or cause your system to fail. Scalaz provides you with Validation to validate your data. Validation is an applicative functor. An applicative functor has more structure than a functor but less than a monad.[1]

Motivating Example

So let’s say we have a Version class representing the major and minor version of our software like so:[2]

1
case class Version(major: Int, minor: Int)

Then, a negative value in either of major or minor would be invalid. We could ensure that we never get a negative value in either the major or minor by using require like so:[3]

1
2
3
4
case class Version(major: Int, minor: Int) {
require(major >= 0, "major must be >= 0: %s".format(major))
require(minor >= 0, "minor must be >= 0: %s".format(minor))
}

The problem here is that we’ll have to handle exceptions and we don’t want side-effects. Let’s use Validation to do it in a more functional way.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@ import scalaz._
import scalaz._
@ import Scalaz._
import Scalaz._
// paste mode in Ammonite REPL is { .. CODE HERE .. } and not :paste
@ {
case class Version(major: Int, minor: Int)
object Version {
def createNew(major: Int, minor: Int): Validation[IllegalArgumentException, Version] = {
val isValidMajor = (major >= 0) ? true | false
val isValidMinor = (minor >= 0) ? true | false

(isValidMajor, isValidMinor) match {
case (false, true) => new IllegalArgumentException("major < 0").failure
case (true, false) => new IllegalArgumentException("minor < 0").failure
case (false, false) => new IllegalArgumentException("major and minor < 0").failure
case (true, true) => new Version(major, minor).success
}
}
}
}
defined class Version
defined object Version
@ Version.createNew(-1, -1)
res5: Validation[IllegalArgumentException, Version] = Failure(
java.lang.IllegalArgumentException: major and minor < 0
)
@ Version.createNew(1, 1)
res6: Validation[IllegalArgumentException, Version] = Success(Version(1, 1))

What we’ve done here is add a createNew to the companion object of Version that returns a Validation. Validating the input can result in either a Success or Failure. We create a Success by calling success on the value and a Failure by calling failure on the value. Once we have a Validation, there are numerous ways in which we can deal with it.

Providing Default Values

1
2
3
4
5
6
@ val invalid = Version.createNew(-1, -1)
invalid: Validation[IllegalArgumentException, Version] = Failure(
java.lang.IllegalArgumentException: major and minor < 0
)
@ val default = invalid | new Version(1, 0)
default: Version = Version(1, 0)

There’s a convenient | operator (getOrElse) that lets you provide a default value if the result of the validation is a Failure. Here we are assigning the value 1 to major and 0 to minor.

Folding a Validation

1
2
3
4
5
6
7
8
9
10
11
12
@ val valid = Version.createNew(1, 0)
valid: Validation[IllegalArgumentException, Version] = Success(Version(1, 0))
@ valid fold(
f => s"Validation failed because ${f getMessage}".println,
v => s"Version is $v".println
)
"Version is Version(1,0)"
@ invalid fold(
f => s"Validation failed because ${f getMessage}".println,
v => s"Version is $v".println
)
"Validation failed because major and minor < 0"

Akin to a disjunction, it’s possible to fold a Validation. Failure will be the first argument and Success will be the second. If you want to fold just on the Success part, you can use foldRight.


NOTE:

Both fold and foldRight should return values. Here I’ve just printed out the values to the console which is a side-effect. I’ve done this to keep the examples simple.


Composing Validations

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@ {
case class Version(major: Int, minor: Int)
object Version {
def isValidMajor(major: Int) =
(major >= 0) ?
major.success[IllegalArgumentException] |
new IllegalArgumentException("major < 0").failure

def isValidMinor(minor: Int) =
(minor >= 0) ?
minor.success[IllegalArgumentException] |
new IllegalArgumentException("minor < 0").failure

def createNew(major: Int, minor: Int) = {
(isValidMajor(major).toValidationNel |@| isValidMinor(minor).toValidationNel) {
Version(_, _)
}
}
}
}
defined class Version
defined object Version

When we started building the Version example, we used pattern matching to check if the major and minor versions were correct. However, there’s a more succinct way to collect all the errors. In the example above, we’ve turned isValidMajor and isValidMinor into methods that return a Validation instead of simply a Boolean.

The magic is in createNew. Here we convert the Validation into a NonEmptyList. toValidationNel wraps the Failure in a NonEmptyList but keeps the Success as-is. The |@| is an ApplicativeBuilder which lets us combine the failures together. If we get all successes, we construct a Version out of it. Let’s see this in action:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@ val bothInvalid = Version.createNew(-1, -1)
bothInvalid: Validation[NonEmptyList[IllegalArgumentException], Version] = Failure(
NonEmpty[java.lang.IllegalArgumentException: major < 0,java.lang.IllegalArgumentException: minor < 0]
)

@ val majorInvalid = Version.createNew(-1, 0)
majorInvalid: Validation[NonEmptyList[IllegalArgumentException], Version] = Failure(
NonEmpty[java.lang.IllegalArgumentException: major < 0]
)

@ val minorInvalid = Version.createNew(1, -1)
minorInvalid: Validation[NonEmptyList[IllegalArgumentException], Version] = Failure(
NonEmpty[java.lang.IllegalArgumentException: minor < 0]
)

@ val bothValid = Version.createNew(1, 1)
bothValid: Validation[NonEmptyList[IllegalArgumentException], Version] = Success(Version(1, 1))

So, in case of both the major and minor being invalid, we get a non-empty list with both the errors in it. This is very convenient and also very extensible. If you need to add an extra check, you can write a new isValidXXX method and make it return a Validation. You can then use the ApplicativeBuilder to your advantage. Using simply booleans would need checking a large number of possible cases.

Mapping Success and Failure

1
2
3
4
5
@ val errMsgs = bothInvalid bimap(
f => f map { _.getMessage },
identity,
)
errMsgs: Validation[NonEmptyList[String], Version] = Failure(NonEmpty[major < 0,minor < 0])

It’s possible to map over Success and Failure and apply any transformations you want. For example, we represent errors with IllegalArgumentExceptions and we may be coding a rest API and we’d like to send back the strings representing the errors. In the example above, I’ve used bimap to map Success and Failure. For every failure, I am extracting the string using getMessage and leaving the success as-is by using identity.

1
2
3
4
5
@ val theVersion = bothValid bimap(
f => f map { _.getMessage },
identity,
)
theVersion: Validation[NonEmptyList[String], Version] = Success(Version(1, 1))

Similar to bimap is map which just maps the Success part of the Validation.

1
2
@ val theValue = bothValid map { v => Version(v.major + 1, v.minor * 2) }
theValue: Validation[NonEmptyList[IllegalArgumentException], Version] = Success(Version(2, 2))

Remember that bimap and map return a Validation. They don’t extract values out of it. You’ll have to use fold, etc. to get the values out.

Running a Side-Effect on Success

1
2
@ bothValid foreach { v => s"Begin build process for version $v".println }
"Begin build process for version Version(1,1)"

foreach lets you run a side-effecting function if the result of the Validation is a Success. For example, using the Version, you could begin a build process or similar.

Checking if it is a Success or Failure

1
2
3
4
5
6
7
8
9
10
11
@ val isSuccess = bothValid isSuccess
isSuccess: Boolean = true

@ val isFailure = bothInvalid isFailure
isFailure: Boolean = true

@ val isSuccessSatisfying = bothValid exists { _.major < 5 }
isSuccessSatisfying: Boolean = true

@ val isSuccessSatisfyingOrFailure = bothValid forall { _.major === 5 }
isSuccessSatisfyingOrFailure: Boolean = false

There are numerous ways in which we can check if the Validation resulted in a Success or a Failure. The simplest way is to use one of isSuccess or isFailure. Similarly, exists will return true if the validation is a success value satisfying the given predicate and forall will return true if the validation is a failure value or the success value satisfies the given predicate.

Converting to Other Datatypes

1
2
3
4
5
6
7
8
@ val list = bothValid toList
list: List[Version] = List(Version(1, 1))

@ val stream = bothValid toStream
stream: Stream[Version] = Stream(Version(1, 1))

@ val either = bothValid toEither
either: Either[NonEmptyList[IllegalArgumentException], Version] = Right(Version(1, 1))

Scalaz also provides convenience methods to convert the Validation to different datatypes like List, Stream, Either, etc.

Conclusion

There’s a lot more methods than can be covered in a post. Hopefully this post gave you an idea about what’s possible with Validations.

In this post we’ll look at MapOps and the goodies it provides to work with Maps. Examples galore!

Altering a Map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@ import scalaz._
import scalaz._
@ import Scalaz._
import Scalaz._

// create two maps
@ val m1 = Map("a" -> 1, "b" -> 2)
m1: Map[String, Int] = Map("a" -> 1, "b" -> 2)
@ val m2 = Map("b" -> 2, "c" -> 3)
m2: Map[String, Int] = Map("b" -> 2, "c" -> 3)

// alter an existing key
@ m1.alter("b") { maybeValue => maybeValue some { v => some(v + 1) } none { some(0) } }
res4: Map[String, Int] = Map("a" -> 1, "b" -> 3)

alter lets you change the values associated with keys. In the example, we’re altering the value associated with key b. Since there may or may not be a value associated with b, we get an Option which we’ve named as maybeValue. We then use the some { ... } none { ... } construct to either add 1 in case there’s a value or initialize the key with 0. Also, since we need to return Options, we use some and none again.

1
2
@ m1.alter("d") { maybeValue => maybeValue some { v => some(v + 1) } none { some(0) } }
res5: Map[String, Int] = Map("a" -> 1, "b" -> 2, "d" -> 0)

If the key does not exist, it will be added to the map.

Intersection

1
2
3
4
@ m1.intersectWith(m2) { _ + _ }
res6: Map[String, Int] = Map("b" -> 4)
@ m1.intersectWith(m2)((v1, v2) => v1 + v2)
res7: Map[String, Int] = Map("b" -> 4)

intersectWith lets you calculate the intersection of two maps. It expects a function that will accept values v1 and v2 from both the maps and return a new value which will become the value associated with the key in the new map. If you want to analyze the key before returning the value, you can use intersectWithKey which expects a function (k, v1, v2) => { ... }.

Mapping Keys

1
2
@ m1 mapKeys { _.toUpperCase }
res8: Map[String, Int] = Map("A" -> 1, "B" -> 2)

mapKeys lets you change the keys without changing the values associated with them. Here, we’re converting them to uppercase.

Union

1
2
3
4
@ m1.unionWith(m2){ _ + _ }
res9: Map[String, Int] = Map("a" -> 1, "b" -> 4, "c" -> 3)
@ m1.unionWith(m2)((v1, v2) => v1 + v2)
res10: Map[String, Int] = Map("a" -> 1, "b" -> 4, "c" -> 3)

unionWith lets you calculate the union of two maps and expects a function that will accept values v1 and v2 from both maps and return a new value which will become the value associated with the key in the new map. Similarly, there’s unionWithKey which will pass the key as the first argument to the function.

Inserting a Value

1
2
3
4
5
6
@ m1.insertWith("a", 99) { _ + _ }
res11: Map[String, Int] = Map("a" -> 100, "b" -> 2)
@ m1.insertWith("a", 99)((v1, v2) => v1 + v2)
res12: Map[String, Int] = Map("a" -> 100, "b" -> 2)
@ m1.insertWith("z", 100) { _ + _ }
res13: Map[String, Int] = Map("a" -> 1, "b" -> 2, "z" -> 100)

insertWith lets you insert a new key-value pair into the map. It also expects a function which will take values v1 and v2 as arguments to deal with cases where the key you’re trying to add already exists.

Conclusion

This brings us to the end of the post on MapOps. These extra functions make it very easy to work with an immutable Map by providing extra functionality not present in the Scala core library.

In this post we’ll look at BooleanOps and the goodies it provides to work with Booleans. As always, we’ll go straight to examples.

Unless

1
2
3
4
5
6
7
8
9
10
11
12
13
@ import scalaz._
import scalaz._
@ import Scalaz._
import Scalaz._
@ val t = true
t: Boolean = true
@ val f = false
f: Boolean = false
// executes the given side-effect if this boolean value is false
@ t unless "this won't print".println

@ f unless "this will print".println
"this will print"

As the comment for unless states:

Executes the given side-effect if this boolean value is false.

A mnemonic to remember the working is: “Unless the value is true, execute the side-effecting function”.

When

1
2
3
4
5
// executes the given side-effect if this boolean value is true
@ t when "this will print".println
"this will print"

@ f when "this won't print".println

The “opposite” of unless is when which executes the function when the value is true. As the comment for when states:

Executes the given side-effect if this boolean value is true.

A mnemonic to remember the working is: “When the value is true, execute the side-effecting function”.

Folding a Boolean

1
2
3
4
@ t fold[String]("this will be returned when true", "this will be returned when false")
res8: String = "this will be returned when true"
@ f fold[String]("this will be returned when true", "this will be returned when false")
res9: String = "this will be returned when false"

fold lets you decide what value to return depending on whether it is true or false.

Converting to an Option

1
2
3
4
@ t option "this will create a Some() with this string in it"
res10: Option[String] = Some("this will create a Some() with this string in it")
@ f option "this will result in a None"
res11: Option[String] = None

option lets us convert a Boolean into an Option in a type-safe manner. A true results in a Some containing the value passed to option whereas a false results in an Option of whatever the type of the argument is.

Ternary Operator

1
2
3
4
@ t ? "true" | "false"
res13: String = "true"
@ f ? "true" | "false"
res14: String = "false"

Scalaz also provides a ternary operator to work with Booleans. The ternary operator is actually a combination of ? and |. ? is the conditional operator that results in the creation of an object of Conditional and | is a method of that object.

Miscellaneous

1
2
3
4
@ t ?? List(1, 2, 3)
res15: List[Int] = List(1, 2, 3)
@ f ?? List(1, 2, 3)
res16: List[Int] = List()

?? returns the given argument if the value is true, otherwise, the zero element for the type of the given argument. In our case, the “zero” element for List is an empty List.

1
2
3
4
@ t !? List(1, 2, 3)
res17: List[Int] = List()
@ f !? List(1, 2, 3)
res18: List[Int] = List(1, 2, 3)

!? is the opposite of ?? and returns the argument if the value is false or the zero element otherwise.

Conclusion

This brings us to the end of our post on BooleanOps. There’s a lot more functions provided but I’ve chosen to cover those which I feel will be the most useful.

In this post we’ll look at TryOps and the goodies it provides to work with scala.util.Try. To recap, here’s what Try does:

The Try type represents a computation that may either result in an exception, or return a successfully computed value. It’s similar to, but semantically different from the scala.util.Either type.

Converting to a Disjunction

1
2
3
4
5
6
7
8
9
10
11
12
@ import scalaz._
import scalaz._
@ import Scalaz._
import Scalaz._
@ import scala.util.Try
import scala.util.Try
// an operation that may potentially throw an exception
@ val t1 = Try { "1".toInt }
t1: Try[Int] = Success(1)
// converting to a Scalaz disjunction
@ val disjunction = t1 toDisjunction
disjunction: Throwable \/ Int = \/-(1)

The result of a Try is either a Success or a Failure. This can very easily be translated to a Scalaz disjunction. A Success produces a right disjunction whereas a Failure produces a left disjunction.

Converting to a Validation

1
2
@ val validation = t1 toValidation
validation: Validation[Throwable, Int] = Success(1)

Similarly, if this Try were a part of validating your data like checking values in a JSON object, you can convert this to a Scalaz Validation.

Converting to a ValidationNel

1
2
@ val nel = t1 toValidationNel
nel: ValidationNel[Throwable, Int] = Success(1)

ValidationNel is useful for accumulating errors. We’ll cover all of this in coming posts.

Conclusion

This brings us to the end of the post on TryOps. In coming posts we’ll look at Validation type which lets us represent, as you might have guessed, the result of validating an input. Similarly, if we want to accumulate all the results of validating inputs, we use ValidationNel. Both of these are subjects of coming posts.

In this post we’ll look at TupleOps and the goodies it provides to work with Tuples. There’s no TupleOps.scala file in the GitHub repo because the file is generated by GenerateTupleW. You can see the code for TupleOps if you’re using an IDE like IntelliJ. There’s a number of TupleNOps classes like Tuple2Ops[A, B], etc. all the way to Tuple12Ops[A, B].

With that said, let’s jump into examples. We’ll look at what Tuple2Ops provides us. Everything is analogous to Tuple3Ops, etc. It’s just the number of arguments to the methods that will change.

Folding a Tuple

1
2
3
4
5
6
@ import scalaz._
import scalaz._
@ import Scalaz._
import Scalaz._
@ (1, 2) fold( (_1, _2) => _1 + _2 )
res2: Int = 3

fold in Tuple2Ops takes a function which accepts 2 arguments i.e. equal to the arity of the tuple. Here, we’re folding the tuple and adding together its two Int elements but you can do whatever you want.

Converting to IndexedSeq

1
2
@ (1, 2) toIndexedSeq
res3: collection.immutable.IndexedSeq[Int] = Vector(1, 2)

This one is self-explanatory. The tuple is converted to an IndexedSeq.

Mapping Elements in a Tuple

1
2
@ (1, 2) mapElements(_1 => _1 * 2, _2 => _2 * 2)
res4: (Int, Int) = (2, 4)

mapElements in Tuple2Ops takes 2 functions as arguments, 1 for each element of the tuple. The functions are then applied to their corresponding elements and the result is returned as a Tuple. In the example above, we’re just multiplying both the elements by 2.

This is different from the map from the standard library. The map from the standard library only operates on the last element of the tuple.

1
2
@ (1, 2) map (_ * 2)
res5: (Int, Int) = (1, 4)

Conclusion

That’s the end of the post on TupleOps. TupleOps‘s convenience methods can be used to manipulate tuples easily.

In this post we’ll look at StringOps and the goodies it provides to work with Strings. Like we did last time, we’ll jump straight into examples.

Plural

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@ import scalaz._
import scalaz._
@ import Scalaz._
import Scalaz._
// keep the doctor away
@ "apple" plural 2
res2: String = "apples"
// oops!
@ "dress" plural 3
res3: String = "dresss"
// singular
@ "apple" plural 1
res4: String = "apple"
// is it Friday, yet?
@ "day" plural 3
res5: String = "days"

Scalaz provides a convenient plural method on String to get its plural form. Going over the docs for plural:

Returns the same String value if the given value is 1 otherwise pluralises this String by appending an “s” unless this String ends with “y” and not one of [“ay”, “ey”, “iy”, “oy”, “uy”] in which case the ‘y’ character is chopped and “ies” is appended.

This explains why the plural of “dress” was “dresss” with 3 “s”; plural simply appended an “s”. Nonetheless, this is a convenient method.

Non-Empty List

1
2
3
4
@ "list" charsNel
res6: Option[NonEmptyList[Char]] = Some(NonEmpty[l,i,s,t])
@ "" charsNel
res7: Option[NonEmptyList[Char]] = None

charsNel converts the String into an Option[NonEmptyList[Char]]. This method is useful if the string represents a sequence of actions to be taken as characters. For example, “OCOC” could mean “Open, Close, Open, Close” or something and charsNel would convert this into an Option of NonEmptyList[Char]. You can then iterate over the characters and take whatever action you want to.

Parsing

Scalaz provides convenient methods for parsing a String into Boolean, Int, etc. The advantage of using these over standard Scala parsing methods is that these methods return a Validation. You can then fold the Validation object to see whether the value was successfully parsed or resulted in an error. This is good for functional programming as you don’t have to catch exceptions. We’ll first look at the Scala way and then the Scalaz way.

1
2
3
4
5
6
7
8
9
10
11
// Scala way
@ "1".toInt
res8: Int = 1
@ "x".toInt
java.lang.NumberFormatException: For input string: "x"
...
// Scalaz way
@ "1".parseInt.fold(err => "failed parse".println, num => num.println)
1
@ "x".parseInt.fold(err => "failed parse".println, num => num.println)
"failed parse"

It’s also possible to parse values to BigDecimal and BigInt.

1
2
@ "3.14159265358979323846".parseBigDecimal.fold(err => "failed parse".println, num => num.println)
3.14159265358979323846

Conclusion

This covers the convenience methods Scalaz provides for dealing with Strings. The parseXXX methods are the most useful as they avoid having to deal with an exception.

In this post we’ll look at OptionOps and the goodies it provides to work with Options. We’ll jump straight into examples.

Creating Options

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@ import scalaz._
import scalaz._
@ import Scalaz._
import Scalaz._
// Some
@ some(13)
res2: Option[Int] = Some(13)
// Calling some on a value
// Notice something about res variable? ;)
@ 13.some
res9: Option[Int] = Some(13)
// None
@ none
res3: Option[Nothing] = None
@ none[Int]
res4: Option[Int] = None

Extracting Values

1
2
3
4
5
6
7
8
9
10
11
12
// using unary ~ operator
@ ~ res2
res5: Int = 13
// using some / none
@ res2 some { _ * 2 } none { 0 }
res6: Int = 26
// using | operator
@ res2 | 0
res7: Int = 13
// extracting value from none
@ ~ res4
res8: Int = 0

The unary ~ extracts the value from the Option or returns the zero value for that type. For example, in case of Int it’ll return the value in the Option or return 0. The some{ .. } none { .. } construct lets you specify what value to return in case of Some and None. I am multiplying the value by 2 and thus returning 26. As you can see, Scalaz provides with more expressive and type-safe way to create and extract values from Option.

Notice that the type of all the resulting variables is Option instead of Some or None. This is more type-safe than using None because you’d get None.type, and the type inferencer would allow the type to be Option[Int] or Option[String] whereas none[Int] is guaranteed to be an Option[Int]. The type inferencer will enforce this.

Miscellaneous

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// we'll have fun with these values
@ val o = some("option")
o: Option[String] = Some("option")
@ val n = none[String]
n: Option[String] = None

// None to right disjunction
@ n toRightDisjunction "onTheLeft"
res10: String \/ String = -\/("onTheLeft")
// Folding the disjunction prints the value on the left
@ res10 fold(l => s"Left: $l".println, r => s"Right: $r".println)
"Left: onTheLeft"

// Some to right disjunction
@ o toRightDisjunction "onTheLeft"
res11: String \/ String = \/-("option")
// Folding the disjunction prints the value on the right
@ res11 fold(l => s"Left: $l".println, r => s"Right: $r".println)
"Right: option"

// default values, similar to unary ~
@ n.orZero
res12: String = ""

// ternary operator
@ o ? "some" | "none"
res13: String = "some"

Scalaz provides us with a disjunction which is a replacement for Scala Either. I’ve only introduced disjunction here and will cover it later in a post of its own. Trying to convert a None to a right disjunction doesn’t work. We get back a left disjunction as indicated by -\/. Similarly, converting a Some to right disjunction works, as indicated by \/-. Scalaz also provides a ternary operator to work with Options.

Conclusion

This sums up, non-exhaustively, how we can use the convenience methods that Scalaz provides on top of Options that lets us code in more expressive and type-safe way.

In this post we’ll look at how to create enum using Scalaz. However, we’ll first look at how to create enum using standard Scala library.

Enum - Scala Way

An enum type is a special data type that enables for a variable to be a set of predefined constants. The variable must be equal to one of the values that have been predefined for it. Common examples include compass directions (values of NORTH, SOUTH, EAST, and WEST) and the days of the week.[1]

There are a couple of ways in which you can create enum in Scala.

Using scala.Enumeration

Defines a finite set of values specific to the enumeration. Typically these values enumerate all possible forms something can take and provide a lightweight alternative to case classes.

Let’s see an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@ object Direction extends Enumeration {
type Direction = Value
val NORTH, EAST, WEST, SOUTH = Value
}
defined object Direction
@ import Direction._
import Direction._
@ Direction withName "NORTH"
res2: Value = NORTH
@ Direction.values foreach println
NORTH
EAST
WEST
SOUTH

Advantages:

  • Lightweight.
  • Easy to use.
  • Iterable.
  • Disadvantages:

  • They only exist as unique values. You cannot add behavior to them.
  • Using Case Objects

    Enum can also be created using sealed trait. A sealed trait requires all the classes or traits extending it be in the same file in which it is defined.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @ object Direction {
    sealed trait Direction
    case object NORTH extends Direction
    case object EAST extends Direction
    case object WEST extends Direction
    case object SOUTH extends Direction
    }
    defined object Direction
    @ import Direction._
    import Direction._

    Advantages:

  • Each value is an instance of its own type and it's possible to add behavior to them.
  • Disadvantages:

  • A case object generates a lot more code than `Enumeration`.
  • Not iterable.
  • Enum - Scalaz Way

    Scalaz allows creating enum using Enum trait. Scalaz enums are more powerful than the standard Scala enums. Let’s see some examples of creating Scalaz enum[2]:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    @ import scalaz._
    import scalaz._
    @ import Scalaz._
    import Scalaz._
    // as a List
    @ 'a' |-> 'z'
    res3: List[Char] = List(
    'a',
    'b',
    'c',
    'd',
    'e',
    'f',
    ...
    // as a Scalaz stream
    @ 'a' |=> 'z'
    res4: EphemeralStream[Char] = scalaz.EphemeralStream$$anon$5@2fb4925c

    Scalaz also provides us with succ and pred to get the successor and predecessor.

    1
    2
    3
    4
    @ 'B'.succ
    res6: Char = 'C'
    @ 'B'.pred
    res7: Char = 'A'

    It’s also possible to easily step through the enumeration.

    1
    2
    3
    4
    5
    6
    // 3 steps forwards
    @ 'B' -+- 3
    res8: Char = 'E'
    // 3 steps backwards
    @ 'B' --- 3
    res9: Char = '?'

    You can also get min and max values for an enumeration.

    1
    2
    3
    4
    @ implicitly[Enum[Int]].min
    res10: Option[Int] = Some(-2147483648)
    @ implicitly[Enum[Int]].max
    res11: Option[Int] = Some(2147483647)

    Let’s create our own enumeration using Scalaz Enum.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    @ import scalaz._
    import scalaz._
    @ import Scalaz._
    import Scalaz._
    @ object Size {
    case class Size(val size: Int, val name: String)
    val SMALL = Size(0, "SMALL")
    val MEDIUM = Size(1, "MEDIUM")
    val LARGE = Size(2, "LARGE")

    implicit object SizeEnum extends Enum[Size] with Show[Size] {
    def order(s1: Size, s2: Size): Ordering = (s1.size compare s2.size) match {
    case -1 => Ordering.LT
    case 0 => Ordering.EQ
    case 1 => Ordering.GT
    }

    def succ(s: Size): Size = s match {
    case SMALL => MEDIUM
    case MEDIUM => LARGE
    case LARGE => SMALL
    }

    def pred(s: Size): Size = s match {
    case SMALL => LARGE
    case MEDIUM => SMALL
    case LARGE => MEDIUM
    }

    def zero: Size = SMALL

    override def shows(s: Size) = s.name

    override def max = Some(LARGE)

    override def min = Some(SMALL)
    }
    }
    defined object Size
    @ import Size._
    import Size._
    // step through
    @ SMALL -+- 1
    res4: Size = Size(1, "MEDIUM")
    // as a list
    @ SMALL |-> LARGE
    res5: List[Size] = List(Size(0, "SMALL"), Size(1, "MEDIUM"), Size(2, "LARGE"))
    // show
    @ SMALL.println
    SMALL
    // max
    @ implicitly[Enum[Size]].max
    res6: Option[Size] = Some(Size(2, "LARGE"))
    // min
    @ implicitly[Enum[Size]].min
    res7: Option[Size] = Some(Size(0, "SMALL"))

    Notice that since we’re using implicitly[], we don’t have to provide the exact name of the typeclass extending Enum[Size], the compiler will figure it out from the implicits within scope.

    Conclusion

    Although Scalaz Enum may seem like a long-winded way to do something trivial, they offer you a lot more flexibility and brevity over vanilla Scala enum. However, I believe that the full force of Scalaz Enum is needed only when you have ordered elements like size. For cases like compass directions, Scala enum are better-suited.

    In this post we’ll look at Scalaz Show. The only purpose of this trait is to provide a String representation for its subtypes.

    A Simple Example

    1
    2
    3
    4
    5
    6
    7
    8
    @ import scalaz._
    import scalaz._
    @ import Scalaz._
    import Scalaz._
    @ 3.show
    res2: Cord = Cord(1 [3])
    @ 3.println
    3

    As always, there are implicits defined for Int, Float, etc. Calling println returns a String whereas calling show returns a Cord. Going over the source code for Cord:

    A Cord is a purely functional data structure for efficiently storing and manipulating Strings that are potentially very long.

    Why Use Show?

    A reasonable question to ask is why use Show when we have a toString which produces a String representation of objects. The answer is that toSring doesn’t always produce a useful representation.

    1
    2
    @ println(new Thread())
    Thread[Thread-185,5,main]

    Showing a Thread

    So, let’s create a Show for Thread.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @ implicit object ThreadShowable extends Show[Thread] {
    override def shows(t: Thread): String = s"Thread Id=${t.getId} name=${t.getName}"
    }
    defined object ThreadShowable
    @ val t = new Thread()
    t: Thread = Thread[Thread-322,5,main]
    // Scala way
    @ println(t)
    Thread[Thread-322,5,main]
    // Scalaz way
    @ t.println
    Thread Id=352 name=Thread-322

    Conclusion

    Show is probably not that interesting and probably exists because there is Show class in Haskell[1]:

    The instances of class Show are those types that can be converted to character strings (typically for I/O)

    In this post we’ll look at how to implement ordering using Scalaz Order trait. However, before we do that, let’s step back a little and look at how we implement ordering using scala.math.Ordering

    Sorting a Collection - Scala Way

    Say we have a List and we’d like to sort it.[1] We can do so by calling the sorted method on it and it’ll work out-of-the-box for lists of Int, Float, etc. because there is an implicit in scala.math.Ordering.

    1
    2
    @ List(1, 2, 3, 5, 4, 10, -1, 0).sorted
    res0: List[Int] = List(-1, 0, 1, 2, 3, 4, 5, 10)

    Going over the documentation for scala.math.Ordering[2]:

    Ordering is a trait whose instances each represent a strategy for sorting instances of a type.
    Ordering’s companion object defines many implicit objects to deal with subtypes of AnyVal (e.g. Int, Double), String, and others.

    All the implicit objects in the companion object implement the scala.math.Ordering trait which extends the java.util.Comparator interface. Thus, they all have a compare method. What if we have types for which there is no sorting strategy in the companion object of scala.math.Ordering? We define our own like so:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @ case class Salary(amt: Float)
    defined class Salary
    @ implicit object SalaryOrdered extends Ordering[Salary] {
    // we are using compare on type Float
    def compare(a: Salary, b: Salary): Int = a.amt compare b.amt
    }
    defined object SalaryOrdered
    @ List(Salary(999.0f), Salary(555.0f)).sorted
    res4: List[Salary] = List(Salary(555.0F), Salary(999.0F))

    But we still don’t have operators like <, <=, etc. on type Salary.

    1
    2
    3
    4
    5
    @ Salary(999.0f) > Salary(555.0f)
    cmd3.sc:1: value > is not a member of ammonite.$sess.cmd0.Salary
    val res3 = Salary(999.0f) > Salary(555.0f)
    ^
    Compilation Failed

    To do that, the trait scala.math.Ordered would have to be mixed in.

    1
    2
    3
    4
    5
    6
    7
    8
    @ case class Salary(amt: Float) extends Ordered[Salary] {
    override def compare(that: Salary): Int = this.amt compare that.amt
    }
    defined class Salary
    @ Salary(1.0f) < Salary(2.0f)
    res1: Boolean = true
    @ List(Salary(2.0f), Salary(2.0f), Salary(1.0f)).sorted
    res2: List[Salary] = List(Salary(1.0F), Salary(2.0F), Salary(2.0F))

    And we know that if we’re working with a library, we do not have the liberty to mix a trait for our convenience. Also, Scala’s comparison operators are not type safe.

    1
    2
    @ 1 > 2.0
    res4: Boolean = false

    Sorting a Collection - Scalaz Way

    As stated before, Scalaz provides Order trait. Staying with our Salary example, let’s put Scalaz Order to use.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    @ import scalaz._
    import scalaz._
    @ import Scalaz._
    import Scalaz._
    @ case class Salary(amt: Float)
    defined class Salary
    @ implicit object SalaryOrder extends Order[Salary] {
    override def order(a: Salary, b: Salary): Ordering = {
    a.amt compare b.amt match {
    case -1 => Ordering.LT
    case 0 => Ordering.EQ
    case 1 => Ordering.GT
    }
    }
    }
    defined object SalaryOrder

    We’ve defined a way to order Salary objects using Scalaz Order trait via a typeclass. The implicit object needs to provide an implementation for order method which returns an Ordering value. Going over the code for Scalaz Ordering:

    This Ordering is analogous to the Ints returned by scala.math.Ordering.

    Now, we have comparison operators at our disposal. Here’s how we can compare Salary objects using the ?|? operator:

    1
    2
    @ Salary(1.0f) ?|? Salary(2.0f)
    res4: Ordering = LT

    ?|? can also be used with Int, Float, etc. and is type-safe.

    1
    2
    3
    4
    5
    6
    7
    @ 1.0 ?|? 2.0
    res5: Ordering = LT
    @ 1.0 ?!? 2
    cmd6.sc:1: value ?!? is not a member of Double
    val res6 = 1.0 ?!? 2
    ^
    Compilation Failed

    Also, analogous to <, <=, we now have type-safe lt, lte, etc.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @ 1.0 gte 2.0
    res6: Boolean = false
    @ 1 gt 2.0
    cmd8.sc:1: type mismatch;
    found : Double(2.0)
    required: Int
    val res8 = 1 gt 2.0
    ^
    Compilation Failed

    That’s not where the power ends. You can also compare Options seamlessly. Do note that it is some with a lowercase “s”.

    1
    2
    @ some(Salary(1.0f)) ?|? some(Salary(2.0f))
    res8: Ordering = LT

    You can now also use sorted on a collection equally easily. Using Order[A].toScalaOrdering we can get back an object of type scala.math.Ordering which we can use to sort collections.

    1
    2
    3
    4
    @ implicit val salaryOrdering = Order[Salary].toScalaOrdering
    salaryOrdering: math.Ordering[Salary] = scalaz.Order$$anon$1@5b8a5d7c
    @ List(Salary(2.0f), Salary(1.0f), Salary(0.0f)).sorted
    res10: List[Salary] = List(Salary(0.0F), Salary(1.0F), Salary(2.0F))

    Also, since Order trait extends the Equal trait, you get the === operator, too.

    1
    2
    @ Salary(0.0F) === Salary(1.0F)
    res11: Boolean = false

    Conclusion

    By using Scalaz Order trait, we can implement comparison between values in a type-safe and extensible way. There’s seamless transformation from Scalaz Order to scala.math.Ordering which lets us use the sorted method on collections.