Scalaz-core provides essential functional programming abstractions for Scala including type classes, data structures, and monad transformers.
—
Scalaz provides immutable functional data structures designed for composition, safety, and performance in functional programming contexts.
Right-biased either-like type for representing computations that may fail or have two possible outcomes.
sealed abstract class \/[+A, +B] {
/** Map over the right side */
def map[C](f: B => C): A \/ C
/** FlatMap over the right side */
def flatMap[C](f: B => A \/ C): A \/ C
/** Check if this is a left value */
def isLeft: Boolean
/** Check if this is a right value */
def isRight: Boolean
/** Fold both sides */
def fold[C](fa: A => C, fb: B => C): C
/** Swap left and right */
def swap: B \/ A
/** Convert to Either */
def toEither: Either[A, B]
/** Convert to Option, discarding left */
def toOption: Option[B]
/** Get the right value or a default */
def getOrElse[BB >: B](x: => BB): BB
/** Recover from left with a function */
def recover[BB >: B](pf: PartialFunction[A, BB]): A \/ BB
/** Transform left side */
def leftMap[C](f: A => C): C \/ B
}
/** Left constructor */
case class -\/[+A](a: A) extends (A \/ Nothing)
/** Right constructor */
case class \/-[+B](b: B) extends (Nothing \/ B)
object \/ {
/** Create left value */
def left[A, B](a: A): A \/ B = -\/(a)
/** Create right value */
def right[A, B](b: B): A \/ B = \/-(b)
/** Try operation, catching exceptions as left */
def fromTryCatchThrowable[T, E <: Throwable](a: => T)(implicit nn: NotNothing[E], ex: ClassTag[E]): E \/ T
}Usage Examples:
import scalaz._
import Scalaz._
// Creating disjunctions
val success: String \/ Int = \/-(42)
val failure: String \/ Int = -\/("error")
// Mapping and chaining
val result = for {
x <- \/-(10)
y <- \/-(20)
} yield x + y // \/-(30)
// Error handling
val safe = \/.fromTryCatchThrowable[Int, NumberFormatException]("42".toInt)Like Disjunction but designed for error accumulation using Applicative.
sealed abstract class Validation[+E, +A] {
/** Map over success value */
def map[B](f: A => B): Validation[E, B]
/** Applicative apply for error accumulation */
def ap[EE >: E, B](f: => Validation[EE, A => B])(implicit E: Semigroup[EE]): Validation[EE, B]
/** Check if this is a failure */
def isFailure: Boolean
/** Check if this is a success */
def isSuccess: Boolean
/** Fold both cases */
def fold[B](failure: E => B, success: A => B): B
/** Convert to Disjunction */
def disjunction: E \/ A
/** Convert to Option */
def toOption: Option[A]
/** Get success value or default */
def getOrElse[AA >: A](x: => AA): AA
}
/** Failure case */
case class Failure[+E](e: E) extends Validation[E, Nothing]
/** Success case */
case class Success[+A](a: A) extends Validation[Nothing, A]
object Validation {
/** Create success */
def success[E, A](a: A): Validation[E, A] = Success(a)
/** Create failure */
def failure[E, A](e: E): Validation[E, A] = Failure(e)
/** Create success for non-empty list validation */
def successNel[E, A](a: A): ValidationNel[E, A] = Success(a)
/** Create failure for non-empty list validation */
def failureNel[E, A](e: E): ValidationNel[E, A] = Failure(NonEmptyList(e))
}
type ValidationNel[E, +A] = Validation[NonEmptyList[E], A]Usage Examples:
import scalaz._
import Scalaz._
// Error accumulation
val user = (
validateName("John").toValidationNel |@|
validateAge(25).toValidationNel |@|
validateEmail("john@example.com").toValidationNel
) { User(_, _, _) }
// Multiple errors will be accumulated in NonEmptyListA list guaranteed to contain at least one element.
sealed abstract class NonEmptyList[+A] {
/** The first element */
def head: A
/** The rest of the elements */
def tail: List[A]
/** Total size */
def size: Int
/** Map over elements */
def map[B](f: A => B): NonEmptyList[B]
/** FlatMap over elements */
def flatMap[B](f: A => NonEmptyList[B]): NonEmptyList[B]
/** Append another NonEmptyList */
def append[AA >: A](other: NonEmptyList[AA]): NonEmptyList[AA]
/** Prepend an element */
def prepend[AA >: A](a: AA): NonEmptyList[AA]
/** Convert to regular List */
def toList: List[A]
/** Reverse the list */
def reverse: NonEmptyList[A]
/** Take first n elements */
def take(n: Int): List[A]
/** Drop first n elements */
def drop(n: Int): List[A]
/** Zip with another NonEmptyList */
def zip[B](other: NonEmptyList[B]): NonEmptyList[(A, B)]
/** Fold the list */
def foldLeft[B](z: B)(f: (B, A) => B): B
def foldRight[B](z: => B)(f: (A, => B) => B): B
}
object NonEmptyList {
/** Create from head and tail */
def apply[A](head: A, tail: A*): NonEmptyList[A]
/** Create from List (returns Option) */
def fromList[A](list: List[A]): Option[NonEmptyList[A]]
/** Create single element NonEmptyList */
def nel[A](head: A, tail: List[A] = Nil): NonEmptyList[A]
}Stack-safe immutable list implementation.
sealed abstract class IList[+A] {
/** Check if empty */
def isEmpty: Boolean
/** Check if non-empty */
def nonEmpty: Boolean
/** Head element (unsafe) */
def head: A
/** Tail elements (unsafe) */
def tail: IList[A]
/** Safe head */
def headOption: Option[A]
/** Safe tail */
def tailOption: Option[IList[A]]
/** Prepend element */
def ::[AA >: A](a: AA): IList[AA]
/** Append element */
def :+[AA >: A](a: AA): IList[AA]
/** Concatenate with another IList */
def ++[AA >: A](other: IList[AA]): IList[AA]
/** Map over elements */
def map[B](f: A => B): IList[B]
/** FlatMap over elements */
def flatMap[B](f: A => IList[B]): IList[B]
/** Filter elements */
def filter(p: A => Boolean): IList[A]
/** Length of the list */
def length: Int
/** Reverse the list */
def reverse: IList[A]
/** Convert to standard List */
def toList: List[A]
/** Fold operations */
def foldLeft[B](z: B)(f: (B, A) => B): B
def foldRight[B](z: => B)(f: (A, => B) => B): B
}
object IList {
/** Empty IList */
def empty[A]: IList[A]
/** Single element IList */
def single[A](a: A): IList[A]
/** Create from varargs */
def apply[A](as: A*): IList[A]
/** Create from List */
def fromList[A](list: List[A]): IList[A]
}Efficient list-like structure supporting O(1) append operations.
case class DList[A](f: List[A] => List[A]) {
/** Append another DList */
def ++(other: DList[A]): DList[A]
/** Prepend a single element */
def +:(a: A): DList[A]
/** Append a single element */
def :+(a: A): DList[A]
/** Convert to List */
def toList: List[A]
/** Check if empty */
def isEmpty: Boolean
/** Map over elements */
def map[B](f: A => B): DList[B]
/** FlatMap over elements */
def flatMap[B](f: A => DList[B]): DList[B]
}
object DList {
/** Empty DList */
def empty[A]: DList[A]
/** Single element DList */
def single[A](a: A): DList[A]
/** Create from List */
def fromList[A](list: List[A]): DList[A]
}Multiway tree where each node contains a value and a stream of subtrees.
case class Tree[A](rootLabel: A, subForest: Stream[Tree[A]]) {
/** Map over all values in the tree */
def map[B](f: A => B): Tree[B]
/** FlatMap over the tree */
def flatMap[B](f: A => Tree[B]): Tree[B]
/** Get all values in pre-order */
def flatten: Stream[A]
/** Get all values in level-order */
def levels: Stream[Stream[A]]
/** Tree size (number of nodes) */
def size: Int
/** Tree height */
def height: Int
/** Check if tree is a leaf */
def isLeaf: Boolean
/** Convert to TreeLoc (zipper) */
def loc: TreeLoc[A]
/** Pretty print the tree */
def drawTree(implicit sh: Show[A]): String
/** Pre-order traversal */
def pre: Stream[A]
/** Post-order traversal */
def post: Stream[A]
}
object Tree {
/** Create a leaf node */
def leaf[A](a: A): Tree[A] = Tree(a, Stream.empty)
/** Create node with children */
def node[A](root: A, children: Stream[Tree[A]]): Tree[A] = Tree(root, children)
/** Unfold a tree from a seed */
def unfoldTree[A, B](seed: A)(f: A => (B, Stream[A])): Tree[B]
}Zipper for Tree providing navigation and editing capabilities.
case class TreeLoc[A](tree: Tree[A], lefts: Stream[Tree[A]], rights: Stream[Tree[A]], parents: Stream[(Stream[Tree[A]], A, Stream[Tree[A]])]) {
/** Get the current label */
def getLabel: A
/** Set the current label */
def setLabel(a: A): TreeLoc[A]
/** Modify the current label */
def modifyLabel(f: A => A): TreeLoc[A]
/** Get current tree */
def getTree: Tree[A]
/** Set current tree */
def setTree(t: Tree[A]): TreeLoc[A]
/** Move to parent */
def parent: Option[TreeLoc[A]]
/** Move to first child */
def firstChild: Option[TreeLoc[A]]
/** Move to last child */
def lastChild: Option[TreeLoc[A]]
/** Move to left sibling */
def left: Option[TreeLoc[A]]
/** Move to right sibling */
def right: Option[TreeLoc[A]]
/** Move to root */
def root: TreeLoc[A]
/** Check if at root */
def isRoot: Boolean
/** Check if is first child */
def isFirst: Boolean
/** Check if is last child */
def isLast: Boolean
/** Check if is leaf */
def isLeaf: Boolean
/** Insert child at beginning */
def insertDownFirst(t: Tree[A]): TreeLoc[A]
/** Insert child at end */
def insertDownLast(t: Tree[A]): TreeLoc[A]
/** Insert left sibling */
def insertLeft(t: Tree[A]): TreeLoc[A]
/** Insert right sibling */
def insertRight(t: Tree[A]): TreeLoc[A]
/** Delete current node */
def delete: Option[TreeLoc[A]]
}Functional cursor over a List providing O(1) navigation and editing.
case class Zipper[A](lefts: Stream[A], focus: A, rights: Stream[A]) {
/** Move focus left */
def left: Option[Zipper[A]]
/** Move focus right */
def right: Option[Zipper[A]]
/** Move to leftmost position */
def start: Zipper[A]
/** Move to rightmost position */
def end: Zipper[A]
/** Modify the focus */
def modify(f: A => A): Zipper[A]
/** Replace the focus */
def update(a: A): Zipper[A]
/** Insert element to the left */
def insertLeft(a: A): Zipper[A]
/** Insert element to the right */
def insertRight(a: A): Zipper[A]
/** Delete the focus */
def delete: Option[Zipper[A]]
/** Convert back to List */
def toList: List[A]
/** Convert to Stream */
def toStream: Stream[A]
/** Length of the zipper */
def length: Int
/** Check if at start */
def atStart: Boolean
/** Check if at end */
def atEnd: Boolean
}
object Zipper {
/** Create zipper from List */
def fromList[A](list: List[A]): Option[Zipper[A]]
/** Create zipper from Stream */
def fromStream[A](stream: Stream[A]): Option[Zipper[A]]
}Priority queue implemented with bootstrapped skew binomial heaps.
sealed abstract class Heap[A] {
/** Check if heap is empty */
def isEmpty: Boolean
/** Size of the heap */
def size: Int
/** Insert element */
def insert(a: A)(implicit o: Order[A]): Heap[A]
/** Get minimum element */
def minimum: Option[A]
/** Remove minimum element */
def deleteMin(implicit o: Order[A]): Option[Heap[A]]
/** Extract minimum (get and remove) */
def uncons(implicit o: Order[A]): Option[(A, Heap[A])]
/** Union with another heap */
def union(other: Heap[A])(implicit o: Order[A]): Heap[A]
/** Convert to List (sorted) */
def toList(implicit o: Order[A]): List[A]
/** Convert to Stream (sorted) */
def toStream(implicit o: Order[A]): Stream[A]
}
object Heap {
/** Empty heap */
def empty[A]: Heap[A]
/** Single element heap */
def single[A](a: A): Heap[A]
/** Create heap from List */
def fromList[A](list: List[A])(implicit o: Order[A]): Heap[A]
}Scalaz's alternative to Option with better performance characteristics.
sealed abstract class Maybe[+A] {
/** Check if this contains a value */
def isDefined: Boolean
/** Check if this is empty */
def isEmpty: Boolean
/** Map over the contained value */
def map[B](f: A => B): Maybe[B]
/** FlatMap over the contained value */
def flatMap[B](f: A => Maybe[B]): Maybe[B]
/** Get value or default */
def getOrElse[AA >: A](a: => AA): AA
/** Convert to Option */
def toOption: Option[A]
/** Fold with functions for both cases */
def fold[B](ifEmpty: => B)(f: A => B): B
/** Filter with predicate */
def filter(p: A => Boolean): Maybe[A]
/** Check if value satisfies predicate */
def exists(p: A => Boolean): Boolean
/** Check if value satisfies predicate or is empty */
def forall(p: A => Boolean): Boolean
/** Apply side effect if value exists */
def foreach(f: A => Unit): Unit
/** Convert to List */
def toList: List[A]
}
/** Contains a value */
case class Just[+A](a: A) extends Maybe[A]
/** Contains no value */
case object Empty extends Maybe[Nothing]
object Maybe {
/** Create Maybe from value */
def just[A](a: A): Maybe[A] = Just(a)
/** Empty Maybe */
def empty[A]: Maybe[A] = Empty
/** Create from Option */
def fromOption[A](opt: Option[A]): Maybe[A]
/** Create from nullable value */
def fromNullable[A](a: A): Maybe[A]
}Efficient string-like data structure using ropes for O(1) concatenation.
case class Cord(toList: List[String]) {
/** Append another Cord */
def ++(other: Cord): Cord
/** Prepend a String */
def +:(s: String): Cord
/** Append a String */
def :+(s: String): Cord
/** Convert to String */
override def toString: String
/** Length in characters */
def length: Int
/** Check if empty */
def isEmpty: Boolean
/** Take first n characters */
def take(n: Int): Cord
/** Drop first n characters */
def drop(n: Int): Cord
}
object Cord {
/** Empty Cord */
val empty: Cord
/** Create from String */
def apply(s: String): Cord
/** Create from List of Strings */
def fromList(ss: List[String]): Cord
}Install with Tessl CLI
npx tessl i tessl/maven-org-scalaz--scalaz-core-sjs1-2-13