Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create Specialized Variants For Effectual Folds Over Recursive Data Structures #854

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
25 changes: 14 additions & 11 deletions core/shared/src/main/scala/zio/prelude/AssociativeBoth.scala
Expand Up @@ -1213,7 +1213,7 @@ object AssociativeBoth {
*/
implicit def ZIOIdentityBoth[R, E]: IdentityBoth[({ type lambda[+a] = ZIO[R, E, a] })#lambda] =
new IdentityBoth[({ type lambda[+a] = ZIO[R, E, a] })#lambda] {
val any: ZIO[R, E, Any] = ZIO.succeed(())
val any: ZIO[R, E, Any] = ZIO.unit

def both[A, B](fa: => ZIO[R, E, A], fb: => ZIO[R, E, B]): ZIO[R, E, (A, B)] = fa zip fb
}
Expand All @@ -1235,19 +1235,21 @@ object AssociativeBoth {
}

/**
* The `AssociativeBoth` instance for `ZManaged`.
* The `IdentityBoth` instance for `ZManaged`.
*/
implicit def ZManagedAssociativeBoth[R, E]: AssociativeBoth[({ type lambda[+a] = ZManaged[R, E, a] })#lambda] =
new AssociativeBoth[({ type lambda[+a] = ZManaged[R, E, a] })#lambda] {
implicit def ZManagedIdentityBoth[R, E]: IdentityBoth[({ type lambda[+a] = ZManaged[R, E, a] })#lambda] =
new IdentityBoth[({ type lambda[+a] = ZManaged[R, E, a] })#lambda] {
val any: ZManaged[R, E, Any] = ZManaged.unit
def both[A, B](fa: => ZManaged[R, E, A], fb: => ZManaged[R, E, B]): ZManaged[R, E, (A, B)] = fa zip fb
}

/**
* The `AssociativeBoth` instance for failed `ZManaged`.
* The `IdentityBoth` instance for failed `ZManaged`.
*/
implicit def ZManagedFailureAssociativeBoth[R, A]
: AssociativeBoth[({ type lambda[+e] = Failure[ZManaged[R, e, A]] })#lambda] =
new AssociativeBoth[({ type lambda[+e] = Failure[ZManaged[R, e, A]] })#lambda] {
implicit def ZManagedFailureIdentityBoth[R, A]
: IdentityBoth[({ type lambda[+e] = Failure[ZManaged[R, e, A]] })#lambda] =
new IdentityBoth[({ type lambda[+e] = Failure[ZManaged[R, e, A]] })#lambda] {
val any: Failure[ZManaged[R, Any, A]] = Failure.wrap(ZManaged.fail(()))
def both[EA, EB](
fa: => Failure[ZManaged[R, EA, A]],
fb: => Failure[ZManaged[R, EB, A]]
Expand All @@ -1270,10 +1272,11 @@ object AssociativeBoth {
}

/**
* The `AssociativeBoth` instance for `ZSTM`.
* The `IdentityBoth` instance for `ZSTM`.
*/
implicit def ZSTMAssociativeBoth[R, E]: AssociativeBoth[({ type lambda[+a] = ZSTM[R, E, a] })#lambda] =
new AssociativeBoth[({ type lambda[+a] = ZSTM[R, E, a] })#lambda] {
implicit def ZSTMIdentityBothBoth[R, E]: IdentityBoth[({ type lambda[+a] = ZSTM[R, E, a] })#lambda] =
new IdentityBoth[({ type lambda[+a] = ZSTM[R, E, a] })#lambda] {
val any: ZSTM[R, E, Any] = ZSTM.unit
def both[A, B](fa: => ZSTM[R, E, A], fb: => ZSTM[R, E, B]): ZSTM[R, E, (A, B)] = fa zip fb
}

Expand Down
11 changes: 11 additions & 0 deletions core/shared/src/main/scala/zio/prelude/AssociativeFlatten.scala
Expand Up @@ -17,6 +17,7 @@
package zio.prelude

import zio._
import zio.stm.ZSTM
import zio.stream.ZStream

import scala.annotation.implicitNotFound
Expand Down Expand Up @@ -201,6 +202,16 @@ object AssociativeFlatten {
def flatten[A](ffa: ZManaged[R, E, ZManaged[R, E, A]]): ZManaged[R, E, A] = ffa.flatten
}

/**
* The `AssociativeFlatten` and `IdentityFlatten` instance for `ZSTM`.
*/
implicit def ZSTMIdentityFlatten[R, E]: IdentityFlatten[({ type lambda[+a] = ZSTM[R, E, a] })#lambda] =
new IdentityFlatten[({ type lambda[+a] = ZSTM[R, E, a] })#lambda] {
def any: ZSTM[R, E, Any] = ZSTM.unit

def flatten[A](ffa: ZSTM[R, E, ZSTM[R, E, A]]): ZSTM[R, E, A] = ffa.flatten
}

/**
* The `AssociativeFlatten` and `IdentityFlatten` instance for `ZStream`.
*/
Expand Down
11 changes: 11 additions & 0 deletions core/shared/src/main/scala/zio/prelude/ZValidation.scala
Expand Up @@ -389,6 +389,17 @@ object ZValidation extends LowPriorityValidationImplicits {
fa.zipPar(fb)
}

/**
* The `IdentityFlatten` instance for `ZValidation`.
*/
implicit def ZValidationIdentityFlatten[W, E]: IdentityFlatten[({ type lambda[+a] = ZValidation[W, E, a] })#lambda] =
new IdentityFlatten[({ type lambda[+a] = ZValidation[W, E, a] })#lambda] {
val any: Validation[Nothing, Any] =
ZValidation.unit
def flatten[A](ffa: ZValidation[W, E, ZValidation[W, E, A]]): ZValidation[W, E, A] =
ffa.flatten
}

/**
* Derives a `PartialOrd[ZValidation[W, E, A]]` given an `Ord[E]` and an `Ord[A]`.
*/
Expand Down
21 changes: 21 additions & 0 deletions core/shared/src/main/scala/zio/prelude/recursive/Recursive.scala
Expand Up @@ -2,6 +2,8 @@ package zio.prelude.recursive

import zio._
import zio.prelude._
import zio.prelude.fx._
import zio.stm._

final case class Recursive[Case[+_], +Annotations](
caseValue: Case[Recursive[Case, Annotations]],
Expand All @@ -16,8 +18,27 @@ final case class Recursive[Case[+_], +Annotations](
): F[Z] =
fold[F[Z]](_.flip.flatMap(f))

def foldManaged[R, E, Z](f: Case[Z] => ZManaged[R, E, Z])(implicit foreach: ForEach[Case]): ZManaged[R, E, Z] =
foldM(f)

def foldPure[W, S, R, E, Z](f: Case[Z] => ZPure[W, S, S, R, E, Z])(implicit
foreach: ForEach[Case]
): ZPure[W, S, S, R, E, Z] =
foldM(f)

def foldRecursive[Z](f: Case[(Recursive[Case, Annotations], Z)] => Z)(implicit covariant: Covariant[Case]): Z =
f(caseValue.map(recursive => recursive -> recursive.foldRecursive(f)))

def foldSTM[R, E, Z](f: Case[Z] => ZSTM[R, E, Z])(implicit foreach: ForEach[Case]): ZSTM[R, E, Z] =
foldM(f)

def foldValidation[W, E, Z](f: Case[Z] => ZValidation[W, E, Z])(implicit
foreach: ForEach[Case]
): ZValidation[W, E, Z] =
foldM(f)

def foldZIO[R, E, Z](f: Case[Z] => ZIO[R, E, Z])(implicit foreach: ForEach[Case]): ZIO[R, E, Z] =
foldM(f)
}

object Recursive {
Expand Down