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 0.7.4
- nscala_time 1.0.0
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:
- Importing
scalaz.contrib.spire._
enables the manual mode. It adds the methodsasSpire
andasScalaz
on type class instances. - Importing either
scalaz.contrib.spire.conversions.toSpire._
orscalaz.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. forRig
andSemiring
).
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:
- Scalaz provides only one-operator classes, namely
Semigroup
andMonoid
. To make a distinction between additive and multiplicative operations, scalaz uses tags. Hence, aSemigroup[A]
denotes an unspecified operation, andSemigroup[A @@ Multiplication]
a multiplicative operation. - Spire provides one- and two-operator classes. The one-operator classes come in three flavours, e.g.
Semigroup
,AdditiveSemigroup
andMultiplicativeSemigroup
(same forMonoid
, ...). As in scalaz, a plainSemigroup
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
extendsAdditiveSemigroup
andMultiplicativeSemigroup
. Also, these classes should guarantee that these two distinct operations relate to each other. - Both scalaz and spire provide some notion of equality and ordering.
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
.