CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-scalaz--scalaz-core-sjs1-2-13

Scalaz-core provides essential functional programming abstractions for Scala including type classes, data structures, and monad transformers.

Pending
Overview
Eval results
Files

transformers.mddocs/

Monad Transformers

Monad transformers allow composition of different monadic effects, enabling complex computations that combine multiple computational contexts.

Capabilities

State Transformers

StateT

Stateful computations that can modify state while computing values.

case class StateT[S, F[_], A](runF: S => F[(S, A)]) {
  /** Run the stateful computation */
  def run(initial: S)(implicit F: Monad[F]): F[(S, A)]
  
  /** Execute and return only the final state */
  def exec(initial: S)(implicit F: Monad[F]): F[S]
  
  /** Evaluate and return only the result */
  def eval(initial: S)(implicit F: Monad[F]): F[A]
  
  /** Map over the result value */
  def map[B](f: A => B)(implicit F: Functor[F]): StateT[S, F, B]
  
  /** FlatMap for sequencing stateful computations */
  def flatMap[B](f: A => StateT[S, F, B])(implicit F: Monad[F]): StateT[S, F, B]
  
  /** Transform the state type */
  def mapState[S2](f: S => S2, g: (S2, S) => S2)(implicit F: Functor[F]): StateT[S2, F, A]
  
  /** Transform the inner monad */
  def mapT[G[_]](f: F[(S, A)] => G[(S, A)]): StateT[S, G, A]
  
  /** Lift StateT into another monad transformer */
  def liftM[G[_[_], _]](implicit G: MonadTrans[G], F: Monad[F]): G[StateT[S, F, ?], A]
}

type State[S, A] = StateT[S, Id, A]

object StateT {
  /** Lift a value into StateT */
  def point[S, F[_], A](a: A)(implicit F: Applicative[F]): StateT[S, F, A]
  
  /** Lift an F[A] into StateT */
  def lift[S, F[_], A](fa: F[A])(implicit F: Functor[F]): StateT[S, F, A]
  
  /** Get the current state */
  def get[S, F[_]](implicit F: Applicative[F]): StateT[S, F, S]
  
  /** Set the state */
  def put[S, F[_]](s: S)(implicit F: Applicative[F]): StateT[S, F, Unit]
  
  /** Modify the state */
  def modify[S, F[_]](f: S => S)(implicit F: Applicative[F]): StateT[S, F, Unit]
  
  /** Inspect the state with a function */
  def gets[S, F[_], A](f: S => A)(implicit F: Applicative[F]): StateT[S, F, A]
}

object State {
  /** Create a State computation */
  def apply[S, A](f: S => (S, A)): State[S, A] = StateT[S, Id, A](f)
  
  /** Get the current state */
  def get[S]: State[S, S] = StateT.get[S, Id]
  
  /** Set the state */
  def put[S](s: S): State[S, Unit] = StateT.put[S, Id](s)
  
  /** Modify the state */
  def modify[S](f: S => S): State[S, Unit] = StateT.modify[S, Id](f)
  
  /** Get part of the state */
  def gets[S, A](f: S => A): State[S, A] = StateT.gets[S, Id, A](f)
}

Usage Examples:

import scalaz._
import Scalaz._

// Simple counter state
val increment: State[Int, Int] = for {
  current <- State.get[Int]
  _       <- State.put(current + 1)
  result  <- State.get[Int]
} yield result

val (finalState, result) = increment.run(0)  // (1, 1)

// Stack operations
def push[A](a: A): State[List[A], Unit] = State.modify(a :: _)
def pop[A]: State[List[A], Option[A]] = for {
  stack <- State.get[List[A]]
  _     <- State.put(stack.drop(1))
} yield stack.headOption

val stackOps = for {
  _   <- push(1)
  _   <- push(2)
  top <- pop[Int]
} yield top

val (finalStack, result) = stackOps.run(List.empty[Int])

Reader Transformers

ReaderT (Kleisli)

Computations that read from a shared environment.

case class Kleisli[M[_], -A, +B](run: A => M[B]) {
  /** Apply the Kleisli arrow */
  def apply(a: A): M[B] = run(a)
  
  /** Map over the result */
  def map[C](f: B => C)(implicit M: Functor[M]): Kleisli[M, A, C]
  
  /** FlatMap for sequencing Reader computations */
  def flatMap[C](f: B => Kleisli[M, A, C])(implicit M: Monad[M]): Kleisli[M, A, C]
  
  /** Compose with another Kleisli */
  def compose[C](k: Kleisli[M, C, A])(implicit M: Monad[M]): Kleisli[M, C, B]
  
  /** AndThen composition */
  def andThen[C](k: Kleisli[M, B, C])(implicit M: Monad[M]): Kleisli[M, A, C]
  
  /** Transform the input type */
  def local[AA](f: AA => A): Kleisli[M, AA, B]
  
  /** Transform the inner monad */
  def mapT[N[_]](f: M[B] => N[B]): Kleisli[N, A, B]
  
  /** Lower to function if M is Id */
  def lower(implicit M: M[B] <:< B): A => B
}

type ReaderT[E, F[_], A] = Kleisli[F, E, A]
type Reader[E, A] = ReaderT[E, Id, A]

object Kleisli {
  /** Lift a value into Kleisli */
  def point[M[_], A, B](b: B)(implicit M: Applicative[M]): Kleisli[M, A, B]
  
  /** Lift an M[B] into Kleisli */
  def lift[M[_], A, B](mb: M[B]): Kleisli[M, A, B]
  
  /** Ask for the environment */
  def ask[M[_], A](implicit M: Applicative[M]): Kleisli[M, A, A]
  
  /** Apply a function to the environment */
  def asks[M[_], A, B](f: A => B)(implicit M: Applicative[M]): Kleisli[M, A, B]
}

object Reader {
  /** Create a Reader */
  def apply[E, A](f: E => A): Reader[E, A] = Kleisli[Id, E, A](f)
  
  /** Ask for the environment */
  def ask[E]: Reader[E, E] = Kleisli.ask[Id, E]
  
  /** Apply function to environment */
  def asks[E, A](f: E => A): Reader[E, A] = Kleisli.asks[Id, E, A](f)
}

Usage Examples:

import scalaz._
import Scalaz._

case class Config(host: String, port: Int, database: String)

// Database operations that need config
def connectDb: Reader[Config, String] = Reader { config =>
  s"Connected to ${config.database} at ${config.host}:${config.port}"
}

def queryUser(id: Int): Reader[Config, String] = for {
  connection <- connectDb
  config     <- Reader.ask[Config]
} yield s"$connection - Queried user $id"

val config = Config("localhost", 5432, "myapp")
val result = queryUser(123).run(config)

Writer Transformers

WriterT

Computations that accumulate log values alongside results.

case class WriterT[W, F[_], A](run: F[(W, A)]) {
  /** Map over the result value */
  def map[B](f: A => B)(implicit F: Functor[F]): WriterT[W, F, B]
  
  /** FlatMap for sequencing Writer computations */
  def flatMap[B](f: A => WriterT[W, F, B])(implicit F: Monad[F], W: Semigroup[W]): WriterT[W, F, B]
  
  /** Get only the log */
  def written(implicit F: Functor[F]): F[W]
  
  /** Get only the value */
  def value(implicit F: Functor[F]): F[A]
  
  /** Transform the log */
  def mapLog[W2](f: W => W2)(implicit F: Functor[F]): WriterT[W2, F, A]
  
  /** Transform both log and value */
  def bimap[W2, B](f: W => W2, g: A => B)(implicit F: Functor[F]): WriterT[W2, F, B]
  
  /** Clear the log */
  def reset(implicit F: Functor[F], W: Monoid[W]): WriterT[W, F, A]
  
  /** Swap log and value */
  def swap(implicit F: Functor[F]): WriterT[A, F, W]
}

type Writer[W, A] = WriterT[W, Id, A]

object WriterT {
  /** Create WriterT with log and value */
  def apply[W, F[_], A](log: W, value: A)(implicit F: Applicative[F]): WriterT[W, F, A]
  
  /** Lift a value into WriterT */
  def point[W, F[_], A](value: A)(implicit W: Monoid[W], F: Applicative[F]): WriterT[W, F, A]
  
  /** Lift an F[A] into WriterT */
  def lift[W, F[_], A](fa: F[A])(implicit W: Monoid[W], F: Functor[F]): WriterT[W, F, A]
  
  /** Create with only log */
  def tell[W, F[_]](log: W)(implicit F: Applicative[F]): WriterT[W, F, Unit]
  
  /** Create from F[(W, A)] */
  def writerT[W, F[_], A](fwa: F[(W, A)]): WriterT[W, F, A]
}

object Writer {
  /** Create Writer with log and value */
  def apply[W, A](log: W, value: A): Writer[W, A] = WriterT[W, Id, A]((log, value))
  
  /** Create with only value */
  def value[W: Monoid, A](value: A): Writer[W, A] = Writer(Monoid[W].zero, value)
  
  /** Create with only log */
  def tell[W](log: W): Writer[W, Unit] = Writer(log, ())
}

Usage Examples:

import scalaz._
import Scalaz._

// Computation with logging
def addWithLog(x: Int, y: Int): Writer[String, Int] = 
  Writer(s"Added $x and $y; ", x + y)

def multiplyWithLog(x: Int, y: Int): Writer[String, Int] =
  Writer(s"Multiplied $x and $y; ", x * y)

val computation = for {
  sum     <- addWithLog(3, 4)
  product <- multiplyWithLog(sum, 2)
} yield product

val (log, result) = computation.run  // ("Added 3 and 4; Multiplied 7 and 2; ", 14)

Option/Maybe Transformers

OptionT

Computations that may fail, combining Option with another monad.

case class OptionT[F[_], A](run: F[Option[A]]) {
  /** Map over the contained value */
  def map[B](f: A => B)(implicit F: Functor[F]): OptionT[F, B]
  
  /** FlatMap for sequencing optional computations */
  def flatMap[B](f: A => OptionT[F, B])(implicit F: Monad[F]): OptionT[F, B]
  
  /** Get the value or a default */
  def getOrElse[AA >: A](default: => AA)(implicit F: Functor[F]): F[AA]
  
  /** Get the value or compute alternative */
  def orElse(alternative: => OptionT[F, A])(implicit F: Monad[F]): OptionT[F, A]
  
  /** Check if the value exists */
  def isDefined(implicit F: Functor[F]): F[Boolean]
  
  /** Check if the value is empty */
  def isEmpty(implicit F: Functor[F]): F[Boolean]
  
  /** Filter with predicate */
  def filter(p: A => Boolean)(implicit F: Functor[F]): OptionT[F, A]
  
  /** Fold with functions for both cases */
  def fold[B](ifEmpty: => B)(f: A => B)(implicit F: Functor[F]): F[B]
  
  /** Transform the inner monad */
  def mapT[G[_]](f: F[Option[A]] => G[Option[A]]): OptionT[G, A]
}

object OptionT {
  /** Create OptionT with Some value */
  def some[F[_], A](a: A)(implicit F: Applicative[F]): OptionT[F, A]
  
  /** Create OptionT with None */
  def none[F[_], A](implicit F: Applicative[F]): OptionT[F, A]
  
  /** Lift F[A] into OptionT */
  def liftF[F[_], A](fa: F[A])(implicit F: Functor[F]): OptionT[F, A]
  
  /** Create from F[Option[A]] */
  def optionT[F[_], A](foa: F[Option[A]]): OptionT[F, A]
  
  /** Create from Option[A] */
  def fromOption[F[_], A](oa: Option[A])(implicit F: Applicative[F]): OptionT[F, A]
}

MaybeT

Similar to OptionT but using Scalaz's Maybe type.

case class MaybeT[F[_], A](run: F[Maybe[A]]) {
  /** Map over the contained value */
  def map[B](f: A => B)(implicit F: Functor[F]): MaybeT[F, B]
  
  /** FlatMap for sequencing maybe computations */
  def flatMap[B](f: A => MaybeT[F, B])(implicit F: Monad[F]): MaybeT[F, B]
  
  /** Get the value or a default */
  def getOrElse[AA >: A](default: => AA)(implicit F: Functor[F]): F[AA]
  
  /** Get the value or compute alternative */
  def orElse(alternative: => MaybeT[F, A])(implicit F: Monad[F]): MaybeT[F, A]
  
  /** Check if the value exists */
  def isDefined(implicit F: Functor[F]): F[Boolean]
  
  /** Check if the value is empty */
  def isEmpty(implicit F: Functor[F]): F[Boolean]
}

object MaybeT {
  /** Create MaybeT with Just value */
  def just[F[_], A](a: A)(implicit F: Applicative[F]): MaybeT[F, A]
  
  /** Create MaybeT with Empty */
  def empty[F[_], A](implicit F: Applicative[F]): MaybeT[F, A]
  
  /** Lift F[A] into MaybeT */
  def liftF[F[_], A](fa: F[A])(implicit F: Functor[F]): MaybeT[F, A]
}

Either Transformers

EitherT

Computations that may fail with error values, combining Either with another monad.

case class EitherT[E, F[_], A](run: F[E \/ A]) {
  /** Map over the right value */
  def map[B](f: A => B)(implicit F: Functor[F]): EitherT[E, F, B]
  
  /** FlatMap for sequencing Either computations */
  def flatMap[B](f: A => EitherT[E, F, B])(implicit F: Monad[F]): EitherT[E, F, B]
  
  /** Map over the left (error) value */
  def leftMap[EE](f: E => EE)(implicit F: Functor[F]): EitherT[EE, F, A]
  
  /** Bimap over both sides */
  def bimap[EE, B](f: E => EE, g: A => B)(implicit F: Functor[F]): EitherT[EE, F, B]
  
  /** Fold both sides */
  def fold[B](left: E => B, right: A => B)(implicit F: Functor[F]): F[B]
  
  /** Get right value or default */
  def getOrElse[AA >: A](default: => AA)(implicit F: Functor[F]): F[AA]
  
  /** Recover from error */
  def recover[AA >: A](pf: PartialFunction[E, AA])(implicit F: Functor[F]): EitherT[E, F, AA]
  
  /** Check if this is a right value */
  def isRight(implicit F: Functor[F]): F[Boolean]
  
  /** Check if this is a left value */
  def isLeft(implicit F: Functor[F]): F[Boolean]
  
  /** Swap left and right */
  def swap(implicit F: Functor[F]): EitherT[A, F, E]
}

object EitherT {
  /** Create EitherT with right value */
  def right[E, F[_], A](a: A)(implicit F: Applicative[F]): EitherT[E, F, A]
  
  /** Create EitherT with left value */
  def left[E, F[_], A](e: E)(implicit F: Applicative[F]): EitherT[E, F, A]
  
  /** Lift F[A] into EitherT as right */
  def liftF[E, F[_], A](fa: F[A])(implicit F: Functor[F]): EitherT[E, F, A]
  
  /** Create from F[E \/ A] */
  def eitherT[E, F[_], A](fea: F[E \/ A]): EitherT[E, F, A]
  
  /** Create from E \/ A */
  def fromDisjunction[E, F[_], A](ea: E \/ A)(implicit F: Applicative[F]): EitherT[E, F, A]
}

Usage Examples:

import scalaz._
import Scalaz._

// Database operations that might fail
def findUser(id: Int): EitherT[String, Future, User] = 
  if (id > 0) EitherT.right(Future.successful(User(id, "John")))
  else EitherT.left(Future.successful("Invalid user ID"))

def findProfile(user: User): EitherT[String, Future, Profile] =
  EitherT.right(Future.successful(Profile(user.id, "Developer")))

val result = for {
  user    <- findUser(123)
  profile <- findProfile(user)
} yield UserWithProfile(user, profile)

// result: EitherT[String, Future, UserWithProfile]

List Transformers

ListT

Computations that produce multiple results, combining List with another monad.

case class ListT[M[_], A](run: M[List[A]]) {
  /** Map over the elements */
  def map[B](f: A => B)(implicit M: Functor[M]): ListT[M, B]
  
  /** FlatMap for sequencing list computations */
  def flatMap[B](f: A => ListT[M, B])(implicit M: Monad[M]): ListT[M, B]
  
  /** Filter elements */
  def filter(p: A => Boolean)(implicit M: Functor[M]): ListT[M, A]
  
  /** Take first n elements */
  def take(n: Int)(implicit M: Functor[M]): ListT[M, A]
  
  /** Drop first n elements */
  def drop(n: Int)(implicit M: Functor[M]): ListT[M, A]
  
  /** Append another ListT */
  def ++(other: ListT[M, A])(implicit M: Monad[M]): ListT[M, A]
  
  /** Convert to List in the monad */
  def toList: M[List[A]] = run
}

object ListT {
  /** Create empty ListT */
  def empty[M[_], A](implicit M: Applicative[M]): ListT[M, A]
  
  /** Create ListT with single element */
  def single[M[_], A](a: A)(implicit M: Applicative[M]): ListT[M, A]
  
  /** Lift M[A] into ListT */
  def liftF[M[_], A](ma: M[A])(implicit M: Functor[M]): ListT[M, A]
  
  /** Create from M[List[A]] */
  def listT[M[_], A](mla: M[List[A]]): ListT[M, A]
  
  /** Create from List[A] */
  def fromList[M[_], A](la: List[A])(implicit M: Applicative[M]): ListT[M, A]
}

Combined Transformers

ReaderWriterStateT

Combination of Reader, Writer, and State transformers.

case class ReaderWriterStateT[R, W, S, F[_], A](run: (R, S) => F[(W, A, S)]) {
  /** Map over the result value */
  def map[B](f: A => B)(implicit F: Functor[F]): ReaderWriterStateT[R, W, S, F, B]
  
  /** FlatMap for sequencing computations */
  def flatMap[B](f: A => ReaderWriterStateT[R, W, S, F, B])(implicit F: Monad[F], W: Semigroup[W]): ReaderWriterStateT[R, W, S, F, B]
  
  /** Execute the computation */
  def runRWST(r: R, s: S): F[(W, A, S)] = run(r, s)
  
  /** Execute and return only the result */
  def eval(r: R, s: S)(implicit F: Functor[F]): F[A]
  
  /** Execute and return only the final state */
  def exec(r: R, s: S)(implicit F: Functor[F]): F[S]
  
  /** Execute and return only the log */
  def logged(r: R, s: S)(implicit F: Functor[F]): F[W]
}

type ReaderWriterState[R, W, S, A] = ReaderWriterStateT[R, W, S, Id, A]
type RWST[R, W, S, F[_], A] = ReaderWriterStateT[R, W, S, F, A]
type RWS[R, W, S, A] = ReaderWriterState[R, W, S, A]

object ReaderWriterStateT {
  /** Ask for the environment */
  def ask[R, W, S, F[_]](implicit W: Monoid[W], F: Applicative[F]): ReaderWriterStateT[R, W, S, F, R]
  
  /** Tell (log) a value */
  def tell[R, W, S, F[_]](w: W)(implicit F: Applicative[F]): ReaderWriterStateT[R, W, S, F, Unit]
  
  /** Get the current state */
  def get[R, W, S, F[_]](implicit W: Monoid[W], F: Applicative[F]): ReaderWriterStateT[R, W, S, F, S]
  
  /** Set the state */
  def put[R, W, S, F[_]](s: S)(implicit W: Monoid[W], F: Applicative[F]): ReaderWriterStateT[R, W, S, F, Unit]
  
  /** Modify the state */
  def modify[R, W, S, F[_]](f: S => S)(implicit W: Monoid[W], F: Applicative[F]): ReaderWriterStateT[R, W, S, F, Unit]
}

Usage Examples:

import scalaz._
import Scalaz._

case class Config(debug: Boolean)
type Log = List[String]
type Counter = Int

def increment: ReaderWriterState[Config, Log, Counter, Unit] = for {
  config <- ReaderWriterStateT.ask[Config, Log, Counter, Id]
  count  <- ReaderWriterStateT.get[Config, Log, Counter, Id]
  _      <- ReaderWriterStateT.put[Config, Log, Counter, Id](count + 1)
  _      <- if (config.debug) 
             ReaderWriterStateT.tell[Config, Log, Counter, Id](List(s"Incremented to ${count + 1}"))
           else 
             ReaderWriterStateT.point[Config, Log, Counter, Id, Unit](())
} yield ()

val config = Config(debug = true)
val (log, result, finalState) = increment.run(config, 0)

Install with Tessl CLI

npx tessl i tessl/maven-org-scalaz--scalaz-core-sjs1-2-13

docs

data-structures.md

free-structures.md

index.md

std-instances.md

syntax.md

transformers.md

type-classes.md

tile.json