Skip to content

Commit

Permalink
Consistency for ops classes (typelevel#1456)
Browse files Browse the repository at this point in the history
1. Extend AnyVal when possible, unless there are macro ops
1a. Don't take implicit params in the ops class param list, again unless
    there are macro ops.
2. Make all conversions to ops classes final. They are all declared in
   traits, so users with their own syntax hierarchy have no chance of
   inlining unless they are marked final. Plus, it's consistent.
3. Make all ops class constructor fields private by default, to avoid
   polluting the namespace of the type.

Remove private val part, because scala 2.10 doesn't support it

Ops class guidelines

Add CartesianTest
  • Loading branch information
edmundnoble committed Apr 13, 2017
1 parent 9c3130e commit 19c3a37
Show file tree
Hide file tree
Showing 37 changed files with 124 additions and 92 deletions.
14 changes: 8 additions & 6 deletions core/src/main/scala/cats/syntax/applicative.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@ package cats
package syntax

trait ApplicativeSyntax {
implicit def catsSyntaxApplicativeId[A](a: A): ApplicativeIdOps[A] = new ApplicativeIdOps[A](a)
implicit def catsSyntaxApplicative[F[_], A](fa: F[A])(implicit F: Applicative[F]): ApplicativeOps[F, A] = new ApplicativeOps[F, A](fa)
implicit final def catsSyntaxApplicativeId[A](a: A): ApplicativeIdOps[A] =
new ApplicativeIdOps[A](a)
implicit final def catsSyntaxApplicative[F[_], A](fa: F[A]): ApplicativeOps[F, A] =
new ApplicativeOps[F, A](fa)
}

final class ApplicativeIdOps[A](val a: A) extends AnyVal {
def pure[F[_]](implicit F: Applicative[F]): F[A] = F.pure(a)
}

final class ApplicativeOps[F[_], A](fa: F[A])(implicit F: Applicative[F]) {
def replicateA(n: Int): F[List[A]] = F.replicateA(n, fa)
def unlessA(cond: Boolean): F[Unit] = F.unlessA(cond)(fa)
def whenA(cond: Boolean): F[Unit] = F.whenA(cond)(fa)
final class ApplicativeOps[F[_], A](val fa: F[A]) extends AnyVal {
def replicateA(n: Int)(implicit F: Applicative[F]): F[List[A]] = F.replicateA(n, fa)
def unlessA(cond: Boolean)(implicit F: Applicative[F]): F[Unit] = F.unlessA(cond)(fa)
def whenA(cond: Boolean)(implicit F: Applicative[F]): F[Unit] = F.whenA(cond)(fa)
}
21 changes: 10 additions & 11 deletions core/src/main/scala/cats/syntax/applicativeError.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,34 @@ package syntax
import cats.data.EitherT

trait ApplicativeErrorSyntax {
implicit def catsSyntaxApplicativeErrorId[E](e: E): ApplicativeErrorIdOps[E] =
implicit final def catsSyntaxApplicativeErrorId[E](e: E): ApplicativeErrorIdOps[E] =
new ApplicativeErrorIdOps(e)

implicit def catsSyntaxApplicativeError[F[_], E, A](fa: F[A])(implicit F: ApplicativeError[F, E]): ApplicativeErrorOps[F, E, A] =
implicit final def catsSyntaxApplicativeError[F[_], E, A](fa: F[A])(implicit F: ApplicativeError[F, E]): ApplicativeErrorOps[F, E, A] =
new ApplicativeErrorOps[F, E, A](fa)

}

final class ApplicativeErrorIdOps[E](e: E) {
final class ApplicativeErrorIdOps[E](val e: E) extends AnyVal {
def raiseError[F[_], A](implicit F: ApplicativeError[F, E]): F[A] =
F.raiseError(e)
}

final class ApplicativeErrorOps[F[_], E, A](fa: F[A])(implicit F: ApplicativeError[F, E]) {
def handleError(f: E => A): F[A] =
final class ApplicativeErrorOps[F[_], E, A](val fa: F[A]) extends AnyVal {
def handleError(f: E => A)(implicit F: ApplicativeError[F, E]): F[A] =
F.handleError(fa)(f)

def handleErrorWith(f: E => F[A]): F[A] =
def handleErrorWith(f: E => F[A])(implicit F: ApplicativeError[F, E]): F[A] =
F.handleErrorWith(fa)(f)

def attempt: F[Either[E, A]] =
def attempt(implicit F: ApplicativeError[F, E]): F[Either[E, A]] =
F.attempt(fa)

def attemptT: EitherT[F, E, A] =
def attemptT(implicit F: ApplicativeError[F, E]): EitherT[F, E, A] =
F.attemptT(fa)

def recover(pf: PartialFunction[E, A]): F[A] =
def recover(pf: PartialFunction[E, A])(implicit F: ApplicativeError[F, E]): F[A] =
F.recover(fa)(pf)

def recoverWith(pf: PartialFunction[E, F[A]]): F[A] =
def recoverWith(pf: PartialFunction[E, F[A]])(implicit F: ApplicativeError[F, E]): F[A] =
F.recoverWith(fa)(pf)
}
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/syntax/apply.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package cats
package syntax

private[syntax] trait ApplySyntax1 {
implicit def catsSyntaxUApply[FA](fa: FA)(implicit U: Unapply[Apply, FA]): Apply.Ops[U.M, U.A] =
implicit final def catsSyntaxUApply[FA](fa: FA)(implicit U: Unapply[Apply, FA]): Apply.Ops[U.M, U.A] =
new Apply.Ops[U.M, U.A] {
val self = U.subst(fa)
val typeClassInstance = U.TC
Expand Down
12 changes: 6 additions & 6 deletions core/src/main/scala/cats/syntax/bitraverse.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@ package cats
package syntax

trait BitraverseSyntax extends BitraverseSyntax1 {
implicit def catsSyntaxBitraverse[F[_, _]: Bitraverse, A, B](fab: F[A, B]): BitraverseOps[F, A, B] =
implicit final def catsSyntaxBitraverse[F[_, _]: Bitraverse, A, B](fab: F[A, B]): BitraverseOps[F, A, B] =
new BitraverseOps[F, A, B](fab)
}

private[syntax] trait BitraverseSyntax1 {
implicit def catsSyntaxNestedBitraverse[F[_, _]: Bitraverse, G[_], A, B](fgagb: F[G[A], G[B]]): NestedBitraverseOps[F, G, A, B] =
implicit final def catsSyntaxNestedBitraverse[F[_, _]: Bitraverse, G[_], A, B](fgagb: F[G[A], G[B]]): NestedBitraverseOps[F, G, A, B] =
new NestedBitraverseOps[F, G, A, B](fgagb)
}

final class BitraverseOps[F[_, _], A, B](fab: F[A, B])(implicit F: Bitraverse[F]) {
def bitraverse[G[_]: Applicative, C, D](f: A => G[C], g: B => G[D]): G[F[C, D]] =
final class BitraverseOps[F[_, _], A, B](val fab: F[A, B]) extends AnyVal {
def bitraverse[G[_]: Applicative, C, D](f: A => G[C], g: B => G[D])(implicit F: Bitraverse[F]): G[F[C, D]] =
F.bitraverse(fab)(f, g)
}

final class NestedBitraverseOps[F[_, _], G[_], A, B](fgagb: F[G[A], G[B]])(implicit F: Bitraverse[F]) {
def bisequence(implicit G: Applicative[G]): G[F[A, B]] =
final class NestedBitraverseOps[F[_, _], G[_], A, B](val fgagb: F[G[A], G[B]]) extends AnyVal {
def bisequence(implicit F: Bitraverse[F], G: Applicative[G]): G[F[A, B]] =
F.bisequence(fgagb)
}
12 changes: 7 additions & 5 deletions core/src/main/scala/cats/syntax/cartesian.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,29 @@ package cats
package syntax

private[syntax] trait CartesianSyntax1 {
implicit def catsSyntaxUCartesian[FA](fa: FA)(implicit U: Unapply[Cartesian, FA]): CartesianOps[U.M, U.A] =
implicit final def catsSyntaxUCartesian[FA](fa: FA)(implicit U: Unapply[Cartesian, FA]): CartesianOps[U.M, U.A] =
new CartesianOps[U.M, U.A] {
val self = U.subst(fa)
val typeClassInstance = U.TC
}
}

trait CartesianSyntax extends CartesianSyntax1 {
implicit def catsSyntaxCartesian[F[_], A](fa: F[A])(implicit F: Cartesian[F]): CartesianOps[F, A] =
implicit final def catsSyntaxCartesian[F[_], A](fa: F[A])(implicit F: Cartesian[F]): CartesianOps[F, A] =
new CartesianOps[F, A] {
val self = fa
val typeClassInstance = F
}
}

abstract class CartesianOps[F[_], A] extends Cartesian.Ops[F, A] {
def |@|[B](fb: F[B]): CartesianBuilder[F]#CartesianBuilder2[A, B] =
final def |@|[B](fb: F[B]): CartesianBuilder[F]#CartesianBuilder2[A, B] =
new CartesianBuilder[F] |@| self |@| fb

def *>[B](fb: F[B])(implicit F: Functor[F]): F[B] = F.map(typeClassInstance.product(self, fb)) { case (a, b) => b }
final def *>[B](fb: F[B])(implicit F: Functor[F]): F[B] =
F.map(typeClassInstance.product(self, fb)) { case (_, b) => b }

def <*[B](fb: F[B])(implicit F: Functor[F]): F[A] = F.map(typeClassInstance.product(self, fb)) { case (a, b) => a }
final def <*[B](fb: F[B])(implicit F: Functor[F]): F[A] =
F.map(typeClassInstance.product(self, fb)) { case (a, _) => a }

}
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/syntax/coflatMap.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package cats
package syntax

private[syntax] trait CoflatMapSyntax1 {
implicit def catsSyntaxUCoflatMap[FA](fa: FA)(implicit U: Unapply[CoflatMap, FA]): CoflatMap.Ops[U.M, U.A] = new CoflatMap.Ops[U.M, U.A] {
implicit final def catsSyntaxUCoflatMap[FA](fa: FA)(implicit U: Unapply[CoflatMap, FA]): CoflatMap.Ops[U.M, U.A] = new CoflatMap.Ops[U.M, U.A] {
val self = U.subst(fa)
val typeClassInstance = U.TC
}
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/syntax/comonad.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package cats
package syntax

private[syntax] trait ComonadSyntax1 {
implicit def catsSyntaxUComonad[FA](fa: FA)(implicit U: Unapply[Comonad, FA]): Comonad.Ops[U.M, U.A] =
implicit final def catsSyntaxUComonad[FA](fa: FA)(implicit U: Unapply[Comonad, FA]): Comonad.Ops[U.M, U.A] =
new Comonad.Ops[U.M, U.A] {
val self = U.subst(fa)
val typeClassInstance = U.TC
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/syntax/contravariant.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package syntax
import cats.functor.Contravariant

private[syntax] trait ContravariantSyntax1 {
implicit def catsSyntaxUContravariant[FA](fa: FA)(implicit U: Unapply[Contravariant, FA]): Contravariant.Ops[U.M, U.A] =
implicit final def catsSyntaxUContravariant[FA](fa: FA)(implicit U: Unapply[Contravariant, FA]): Contravariant.Ops[U.M, U.A] =
new Contravariant.Ops[U.M, U.A] {
val self = U.subst(fa)
val typeClassInstance = U.TC
Expand Down
10 changes: 5 additions & 5 deletions core/src/main/scala/cats/syntax/either.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import scala.reflect.ClassTag
import scala.util.{Failure, Success, Try}

trait EitherSyntax {
implicit def catsSyntaxEither[A, B](eab: Either[A, B]): EitherOps[A, B] = new EitherOps(eab)
implicit final def catsSyntaxEither[A, B](eab: Either[A, B]): EitherOps[A, B] = new EitherOps(eab)

implicit def catsSyntaxEitherObject(either: Either.type): EitherObjectOps = new EitherObjectOps(either) // scalastyle:off ensure.single.space.after.token
implicit final def catsSyntaxEitherObject(either: Either.type): EitherObjectOps = new EitherObjectOps(either) // scalastyle:off ensure.single.space.after.token

implicit def catsSyntaxLeft[A, B](left: Left[A, B]): LeftOps[A, B] = new LeftOps(left)
implicit final def catsSyntaxLeft[A, B](left: Left[A, B]): LeftOps[A, B] = new LeftOps(left)

implicit def catsSyntaxRight[A, B](right: Right[A, B]): RightOps[A, B] = new RightOps(right)
implicit final def catsSyntaxRight[A, B](right: Right[A, B]): RightOps[A, B] = new RightOps(right)

implicit def catsSyntaxEitherId[A](a: A): EitherIdOps[A] = new EitherIdOps(a)
implicit final def catsSyntaxEitherId[A](a: A): EitherIdOps[A] = new EitherIdOps(a)
}

final class EitherOps[A, B](val eab: Either[A, B]) extends AnyVal {
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/syntax/eitherK.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package syntax
import cats.data.EitherK

trait EitherKSyntax {
implicit def catsSyntaxEitherK[F[_], A](a: F[A]): EitherKOps[F, A] = new EitherKOps(a)
implicit final def catsSyntaxEitherK[F[_], A](a: F[A]): EitherKOps[F, A] = new EitherKOps(a)
}

final class EitherKOps[F[_], A](val fa: F[A]) extends AnyVal {
Expand Down
1 change: 1 addition & 0 deletions core/src/main/scala/cats/syntax/eq.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package syntax
import cats.macros.Ops

trait EqSyntax {
/** not final so it can be disabled in favor of scalactic equality in tests */
implicit def catsSyntaxEq[A: Eq](a: A): EqOps[A] =
new EqOps[A](a)
}
Expand Down
14 changes: 7 additions & 7 deletions core/src/main/scala/cats/syntax/flatMap.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package cats
package syntax

private[syntax] trait FlatMapSyntax1 {
implicit def catsSyntaxUFlatMap[FA](fa: FA)(implicit U: Unapply[FlatMap, FA]): FlatMap.Ops[U.M, U.A] =
implicit final def catsSyntaxUFlatMap[FA](fa: FA)(implicit U: Unapply[FlatMap, FA]): FlatMap.Ops[U.M, U.A] =
new FlatMap.Ops[U.M, U.A]{
val self = U.subst(fa)
val typeClassInstance = U.TC
Expand All @@ -11,14 +11,14 @@ private[syntax] trait FlatMapSyntax1 {

trait FlatMapSyntax extends FlatMap.ToFlatMapOps with FlatMapSyntax1 {

implicit def catsSyntaxFlatten[F[_]: FlatMap, A](ffa: F[F[A]]): FlattenOps[F, A] =
implicit final def catsSyntaxFlatten[F[_]: FlatMap, A](ffa: F[F[A]]): FlattenOps[F, A] =
new FlattenOps[F, A](ffa)

implicit def catsSyntaxIfM[F[_]: FlatMap](fa: F[Boolean]): IfMOps[F] =
implicit final def catsSyntaxIfM[F[_]: FlatMap](fa: F[Boolean]): IfMOps[F] =
new IfMOps[F](fa)
}

final class FlattenOps[F[_], A](ffa: F[F[A]])(implicit F: FlatMap[F]) {
final class FlattenOps[F[_], A](val ffa: F[F[A]]) extends AnyVal {

/**
* Flatten nested `F` values.
Expand All @@ -32,10 +32,10 @@ final class FlattenOps[F[_], A](ffa: F[F[A]])(implicit F: FlatMap[F]) {
* res0: ErrorOr[Int] = Right(3)
* }}}
*/
def flatten: F[A] = F.flatten(ffa)
def flatten(implicit F: FlatMap[F]): F[A] = F.flatten(ffa)
}

final class IfMOps[F[_]](fa: F[Boolean])(implicit F: FlatMap[F]) {
final class IfMOps[F[_]](val fa: F[Boolean]) extends AnyVal {

/**
* A conditional lifted into the `F` context.
Expand All @@ -56,5 +56,5 @@ final class IfMOps[F[_]](fa: F[Boolean])(implicit F: FlatMap[F]) {
* res1: Int = 0
* }}}
*/
def ifM[B](ifTrue: => F[B], ifFalse: => F[B]): F[B] = F.ifM(fa)(ifTrue, ifFalse)
def ifM[B](ifTrue: => F[B], ifFalse: => F[B])(implicit F: FlatMap[F]): F[B] = F.ifM(fa)(ifTrue, ifFalse)
}
10 changes: 5 additions & 5 deletions core/src/main/scala/cats/syntax/foldable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@ package cats
package syntax

private[syntax] trait FoldableSyntax1 {
implicit def catsSyntaxUFoldable[FA](fa: FA)(implicit U: Unapply[Foldable, FA]): Foldable.Ops[U.M, U.A] =
implicit final def catsSyntaxUFoldable[FA](fa: FA)(implicit U: Unapply[Foldable, FA]): Foldable.Ops[U.M, U.A] =
new Foldable.Ops[U.M, U.A] {
val self = U.subst(fa)
val typeClassInstance = U.TC
}
}

trait FoldableSyntax extends Foldable.ToFoldableOps with FoldableSyntax1 {
implicit def catsSyntaxNestedFoldable[F[_]: Foldable, G[_], A](fga: F[G[A]]): NestedFoldableOps[F, G, A] =
implicit final def catsSyntaxNestedFoldable[F[_]: Foldable, G[_], A](fga: F[G[A]]): NestedFoldableOps[F, G, A] =
new NestedFoldableOps[F, G, A](fga)
}

final class NestedFoldableOps[F[_], G[_], A](fga: F[G[A]])(implicit F: Foldable[F]) {
def sequence_(implicit G: Applicative[G]): G[Unit] = F.sequence_(fga)
final class NestedFoldableOps[F[_], G[_], A](val fga: F[G[A]]) extends AnyVal {
def sequence_(implicit F: Foldable[F], G: Applicative[G]): G[Unit] = F.sequence_(fga)

/**
* @see [[Foldable.foldK]].
Expand All @@ -29,5 +29,5 @@ final class NestedFoldableOps[F[_], G[_], A](fga: F[G[A]])(implicit F: Foldable[
* res0: Set[Int] = Set(1, 2, 3, 4)
* }}}
*/
def foldK(implicit G: MonoidK[G]): G[A] = F.foldK(fga)
def foldK(implicit F: Foldable[F], G: MonoidK[G]): G[A] = F.foldK(fga)
}
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/syntax/functor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package cats
package syntax

private[syntax] trait FunctorSyntax1 {
implicit def catsSyntaxUFunctor[FA](fa: FA)(implicit U: Unapply[Functor, FA]): Functor.Ops[U.M, U.A] =
implicit final def catsSyntaxUFunctor[FA](fa: FA)(implicit U: Unapply[Functor, FA]): Functor.Ops[U.M, U.A] =
new Functor.Ops[U.M, U.A]{
val self = U.subst(fa)
val typeClassInstance = U.TC
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/syntax/functorFilter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package cats
package syntax

private[syntax] trait FunctorFilterSyntax1 {
implicit def catsSyntaxUFunctorFilter[FA](fa: FA)(implicit U: Unapply[FunctorFilter, FA]): FunctorFilter.Ops[U.M, U.A] =
implicit final def catsSyntaxUFunctorFilter[FA](fa: FA)(implicit U: Unapply[FunctorFilter, FA]): FunctorFilter.Ops[U.M, U.A] =
new FunctorFilter.Ops[U.M, U.A]{
val self = U.subst(fa)
val typeClassInstance = U.TC
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/syntax/group.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import cats.macros.Ops

trait GroupSyntax extends SemigroupSyntax {
// TODO: use simulacrum instances eventually
implicit def catsSyntaxGroup[A: Group](a: A): GroupOps[A] =
implicit final def catsSyntaxGroup[A: Group](a: A): GroupOps[A] =
new GroupOps[A](a)
}

Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/syntax/invariant.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package syntax
import cats.functor.Invariant

private[syntax] trait InvariantSyntax1 {
implicit def catsSyntaxUInvariant[FA](fa: FA)(implicit U: Unapply[Invariant, FA]): Invariant.Ops[U.M, U.A] =
implicit final def catsSyntaxUInvariant[FA](fa: FA)(implicit U: Unapply[Invariant, FA]): Invariant.Ops[U.M, U.A] =
new Invariant.Ops[U.M, U.A] {
val self = U.subst(fa)
val typeClassInstance = U.TC
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/syntax/ior.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package cats.syntax
import cats.data.Ior

trait IorSyntax {
implicit def catsSyntaxIorId[A](a: A): IorIdOps[A] = new IorIdOps(a)
implicit final def catsSyntaxIorId[A](a: A): IorIdOps[A] = new IorIdOps(a)
}

final class IorIdOps[A](val a: A) extends AnyVal {
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/syntax/list.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package syntax
import cats.data.NonEmptyList

trait ListSyntax {
implicit def catsSyntaxList[A](la: List[A]): ListOps[A] = new ListOps(la)
implicit final def catsSyntaxList[A](la: List[A]): ListOps[A] = new ListOps(la)
}

final class ListOps[A](val la: List[A]) extends AnyVal {
Expand Down
16 changes: 8 additions & 8 deletions core/src/main/scala/cats/syntax/monad.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ package cats
package syntax

trait MonadSyntax {
implicit def catsSyntaxMonad[F[_]: Monad, A](fa: F[A]): MonadOps[F, A] = new MonadOps(fa)
implicit final def catsSyntaxMonad[F[_], A](fa: F[A]): MonadOps[F, A] = new MonadOps(fa)
}

final class MonadOps[F[_], A](fa: F[A])(implicit M: Monad[F]) {
def whileM[G[_]](p: F[Boolean])(implicit G: Alternative[G]): F[G[A]] = M.whileM(p)(fa)
def whileM_(p: F[Boolean]): F[Unit] = M.whileM_(p)(fa)
def untilM[G[_]](p: F[Boolean])(implicit G: Alternative[G]): F[G[A]] = M.untilM(fa)(p)
def untilM_(p: F[Boolean]): F[Unit] = M.untilM_(fa)(p)
def iterateWhile(p: A => Boolean): F[A] = M.iterateWhile(fa)(p)
def iterateUntil(p: A => Boolean): F[A] = M.iterateUntil(fa)(p)
final class MonadOps[F[_], A](val fa: F[A]) extends AnyVal {
def whileM[G[_]](p: F[Boolean])(implicit M: Monad[F], G: Alternative[G]): F[G[A]] = M.whileM(p)(fa)
def whileM_(p: F[Boolean])(implicit M: Monad[F]): F[Unit] = M.whileM_(p)(fa)
def untilM[G[_]](p: F[Boolean])(implicit M: Monad[F], G: Alternative[G]): F[G[A]] = M.untilM(fa)(p)
def untilM_(p: F[Boolean])(implicit M: Monad[F]): F[Unit] = M.untilM_(fa)(p)
def iterateWhile(p: A => Boolean)(implicit M: Monad[F]): F[A] = M.iterateWhile(fa)(p)
def iterateUntil(p: A => Boolean)(implicit M: Monad[F]): F[A] = M.iterateUntil(fa)(p)
}
Loading

0 comments on commit 19c3a37

Please sign in to comment.