Interoperability libraries & additional data structures and instances for Scalaz
This library is currently available for Scala 2.11 only. For 2.10 builds, use version 0.1.5
.
To use the latest version, include the following in your build.sbt
:
libraryDependencies ++= Seq(
"org.typelevel" %% "scalaz-contrib-210" % "0.2",
"org.typelevel" %% "scalaz-contrib-validation" % "0.2",
"org.typelevel" %% "scalaz-contrib-undo" % "0.2",
// currently unavailable because there's no 2.11 build of Lift yet
// "org.typelevel" %% "scalaz-lift" % "0.2",
"org.typelevel" %% "scalaz-nscala-time" % "0.2",
"org.typelevel" %% "scalaz-spire" % "0.2"
)
For the in-progress features, use the following:
resolvers += Resolver.sonatypeRepo("snapshots")
and depend on version 0.3-SNAPSHOT
instead.
You can now use type class instances for new data types in the standard library:
scala> import scalaz._
import scalaz._
scala> import scalaz.contrib.std.utilTry._
import scalaz.contrib.std.utilTry._
scala> Monad[scala.util.Try]
res1: scalaz.Monad[scala.util.Try] = scalaz.contrib.std.TryInstances1$$anon$1@19ae3dd5
The instance for Scala's Future
is in scalaz proper. Try
remains here.
There are a couple of useful validators and converters, as well as a DSL for checking and transforming values.
import scalaz.contrib.Checker
import scalaz.contrib.validator.all._, scalaz.contrib.converter.all._
import scalaz.std.list._
val c = Checker.check("2012-12-20".toList)
scala> c.checkThat(notEmpty("must be non-empty")(_)).
| map(_.mkString("")).
| convertTo(date("yyyy-MM-dd", "must be a valid date")).
| toValidation
res0: Validation[NonEmptyList[String],Date] = Success(Thu Dec 20 00:00:00 CET 2012)
scala> c.checkThat(notEmpty("must be non-empty")(_)).
| map(_.mkString("")).
| convertTo(uuid("must be a valid UUID")).
| toValidation
res1: Validation[NonEmptyList[String],Date] = Failure(NonEmptyList(must be a valid UUID))
Originally by Gerolf Seitz (@gseitz).
import scalaz.contrib.undo.UndoT
import UndoT._
import scalaz.std.option._
val result = for {
one <- hput[Option, Int](1)
two <- hput[Option, Int](2)
three <- hput[Option, Int](3)
twoAgain <- undo[Option, Int]
four <- hput[Option, Int](4)
twoAgainAgain <- undo[Option, Int]
fourAgain <- redo[Option, Int]
} yield ()
scala> result.exec(1)
res0: Option[Int] = Some(4)
This project provides bindings (instances) for the following libraries:
Spire provides powerful abstractions for numeric programming in Scala, including a full-stack hierarchy of algebraic type classes such as Semigroup
, Monoid
, and Ring
. Scalaz only has the former two, but instead lots of instances. This library provides mappings between type classes where it makes sense.
There are two modes of conversion, manual and automatic:
scalaz.contrib.spire._
enables the manual mode. It adds the methods asSpire
and asScalaz
on type class instances.scalaz.contrib.spire.conversions.toSpire._
or scalaz.contrib.spire.conversions.toScalaz._
(importing both will lead to anarchy) enables the automatic mode. It provides implicit conversions for type class instances. This mode does not provide conversions for two-operator classes (i.e. for Rig
and Semiring
).It is possible (but not recommended) to enable both modes.
To understand which conversions "make sense", consider the kinds of type classes offered by scalaz and spire:
Semigroup
and Monoid
. To make a distinction between additive and multiplicative operations, scalaz uses tags. Hence, a Semigroup[A]
denotes an unspecified operation, and Semigroup[A @@ Multiplication]
a multiplicative operation.Semigroup
, AdditiveSemigroup
and MultiplicativeSemigroup
(same for Monoid
, ...). As in scalaz, a plain Semigroup
conveys nothing about the type of operation, whereas the other two should be used for additive and multiplicative operations, respectively. Spire's two-operator classes inherit from the additive and multiplicative variants, e.g. Semiring
extends AdditiveSemigroup
and MultiplicativeSemigroup
. Also, these classes should guarantee that these two distinct operations relate to each other.Thus, in manual mode, the following conversions are available:
from scalaz one-operator to spire one-operator:
S.asSpire // Semigroup → Semigroup
S.asSpireAdditive // ... → AdditiveSemigroup
S.asSpireMultiplicative // ... → MultiplicativeSemigroup
SMult.asSpire // Semigroup @@ Multiplication → MultiplicativeSemigroup
E.asSpire // Equal → Eq
O.asSpire // Order → Order
from spire one-operator to scalaz one-operator:
// Semigroup and AdditiveSemigroup → Semigroup
// MultiplicativeSemigroup → Semigroup @@ Multiplication
S.asScalaz
// Eq → Equal
// Order → Order
O.asScalaz
These operations are also available in automatic mode, without the need to call asXY
.
from scalaz one-operator to spire two-operator:
// (Semigroup, Semigroup @@ Multiplication) → Semiring
(S, SMult).asSpire
The other direction is for free since the two-operator classes extend the one-operator classes. This operation is not available in automatic mode, since there is no guarantee that two independent scalaz instances obey the necessary laws to form a two-operator class.
Of course, the above mentioned conversions also work for Monoid
and Rig
.