Skip to content

Commit

Permalink
Clean up Selective api
Browse files Browse the repository at this point in the history
  • Loading branch information
danimontoya committed Mar 9, 2021
1 parent 1cd9a90 commit 497a4c0
Show file tree
Hide file tree
Showing 33 changed files with 70 additions and 548 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ import arrow.Kind
import arrow.KindDeprecation
import arrow.core.Either.Right
import arrow.typeclasses.Monoid
import arrow.typeclasses.SelectiveDeprecation
import arrow.typeclasses.Semigroup
import arrow.typeclasses.Show

@Deprecated(
message = KindDeprecation,
level = DeprecationLevel.WARNING
)
class ForOption private constructor() { companion object }
class ForOption private constructor() {
companion object
}

@Deprecated(
message = KindDeprecation,
Expand Down Expand Up @@ -922,13 +925,13 @@ sealed class Option<out A> : OptionOf<A> {
mapConst(Unit)

fun <B> zip(other: Option<B>): Option<Pair<A, B>> =
mapN(this, other) { a, b -> a to b}
mapN(this, other) { a, b -> a to b }

inline fun <B, C> zip(other: Option<B>, f: (A, B) -> C): Option<C> =
zip(other).map { a -> f(a.first, a.second)}
zip(other).map { a -> f(a.first, a.second) }

inline fun <B, C> zipEval(other: Eval<Option<B>>, crossinline f: (A, B) -> C): Eval<Option<C>> =
other.map {zip(it).map { a -> f(a.first, a.second) }}
other.map { zip(it).map { a -> f(a.first, a.second) } }

infix fun <X> and(value: Option<X>): Option<X> = if (isEmpty()) {
None
Expand Down Expand Up @@ -984,7 +987,8 @@ inline fun <T> Option<T>.getOrElse(default: () -> T): T = fold({ default() }, ::
*
* @param alternative the default option if this is empty.
*/
inline fun <A> OptionOf<A>.orElse(alternative: () -> Option<A>): Option<A> = if (fix().isEmpty()) alternative() else fix()
inline fun <A> OptionOf<A>.orElse(alternative: () -> Option<A>): Option<A> =
if (fix().isEmpty()) alternative() else fix()

infix fun <T> OptionOf<T>.or(value: Option<T>): Option<T> = if (fix().isEmpty()) {
value
Expand Down Expand Up @@ -1024,9 +1028,11 @@ fun <T> Iterable<T>.lastOrNone(predicate: (T) -> Boolean): Option<T> = this.last

fun <T> Iterable<T>.elementAtOrNone(index: Int): Option<T> = this.elementAtOrNull(index).toOption()

@Deprecated(SelectiveDeprecation)
fun <A, B> Option<Either<A, B>>.select(f: OptionOf<(A) -> B>): Option<B> =
branch(f.fix(), Some(::identity))

@Deprecated(SelectiveDeprecation)
fun <A, B, C> Option<Either<A, B>>.branch(fa: Option<(A) -> C>, fb: Option<(B) -> C>): Option<C> =
flatMap {
it.fold(
Expand All @@ -1035,21 +1041,6 @@ fun <A, B, C> Option<Either<A, B>>.branch(fa: Option<(A) -> C>, fb: Option<(B) -
)
}

private fun Option<Boolean>.selector(): Option<Either<Unit, Unit>> =
map { bool -> if (bool) Either.right(Unit) else Either.left(Unit) }

fun <A> Option<Boolean>.whenS(x: Option<() -> Unit>): Option<Unit> =
selector().select(x.map { f -> { _: Unit -> f() } })

fun <A> Option<Boolean>.ifS(fl: Option<A>, fr: Option<A>): Option<A> =
selector().branch(fl.map { { _: Unit -> it } }, fr.map { { _: Unit -> it } })

fun Option<Boolean>.orS(f: Option<Boolean>): Option<Boolean> =
ifS(Some(true), f)

fun Option<Boolean>.andS(f: Option<Boolean>): Option<Boolean> =
ifS(f, Some(false))

fun <A> Option<A>.combineAll(MA: Monoid<A>): A = MA.run {
foldLeft(empty()) { acc, a -> acc.combine(a) }
}
Expand Down Expand Up @@ -1204,7 +1195,7 @@ fun <A, B> Option<Pair<A, B>>.unzip(): Pair<Option<A>, Option<B>> =
inline fun <A, B, C> Option<C>.unzip(f: (C) -> Pair<A, B>): Pair<Option<A>, Option<B>> =
fold(
{ Option.empty<A>() to Option.empty() },
{ f(it).let { pair -> Some(pair.first) to Some(pair.second) }}
{ f(it).let { pair -> Some(pair.first) to Some(pair.second) } }
)

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package arrow.core

import arrow.Kind
import arrow.KindDeprecation
import arrow.core.Validated.Companion.mapN
import arrow.typeclasses.Applicative
import arrow.typeclasses.Monoid
import arrow.typeclasses.Semigroup
Expand Down Expand Up @@ -546,7 +547,10 @@ sealed class Validated<out E, out A> : ValidatedOf<E, A> {
* }
* ```
*/
inline fun <A, B, C, D> lift(crossinline fl: (A) -> C, crossinline fr: (B) -> D): (Validated<A, B>) -> Validated<C, D> =
inline fun <A, B, C, D> lift(
crossinline fl: (A) -> C,
crossinline fr: (B) -> D
): (Validated<A, B>) -> Validated<C, D> =
{ fa -> fa.bimap(fl, fr) }

val s = 1.inc()
Expand Down Expand Up @@ -1029,33 +1033,6 @@ operator fun <E : Comparable<E>, A : Comparable<A>> Validated<E, A>.compareTo(ot
{ r1 -> other.fold({ 1 }, { r2 -> r1.compareTo(r2) }) }
)

fun <E, A, B> Validated<E, Either<A, B>>.select(f: Validated<E, (A) -> B>): Validated<E, B> =
fold({ Invalid(it) }, { it.fold({ l -> f.map { ff -> ff(l) } }, { r -> r.valid() }) })

fun <E, A, B, C> Validated<E, Either<A, B>>.branch(fl: Validated<E, (A) -> C>, fr: Validated<E, (B) -> C>): Validated<E, C> =
when (this) {
is Validated.Valid -> when (val either = this.a) {
is Either.Left -> fl.map { f -> f(either.a) }
is Either.Right -> fr.map { f -> f(either.b) }
}
is Validated.Invalid -> this
}

private fun <E> Validated<E, Boolean>.selector(): Validated<E, Either<Unit, Unit>> =
map { bool -> if (bool) Either.leftUnit else Either.unit }

fun <E> Validated<E, Boolean>.whenS(x: Validated<E, () -> Unit>): Validated<E, Unit> =
selector().select(x.map { f -> { f() } })

fun <E, A> Validated<E, Boolean>.ifS(fl: Validated<E, A>, fr: Validated<E, A>): Validated<E, A> =
selector().branch(fl.map { { _: Unit -> it } }, fr.map { { _: Unit -> it } })

fun <E> Validated<E, Boolean>.orS(f: Validated<E, Boolean>): Validated<E, Boolean> =
ifS(Valid(true), f)

fun <E> Validated<E, Boolean>.andS(f: Validated<E, Boolean>): Validated<E, Boolean> =
ifS(f, Valid(false))

/**
* Return the Valid value, or the default if Invalid
*/
Expand Down Expand Up @@ -1148,9 +1125,10 @@ fun <E, A> Validated<E, A>.attempt(): Validated<Nothing, Either<E, A>> =
map { Right(it) }.handleError { Left(it) }

@Deprecated("@extension kinded projected functions are deprecated. Replace with traverse or traverseEither from arrow.core.*")
fun <G, E, A, B> ValidatedOf<E, A>.traverse(GA: Applicative<G>, f: (A) -> Kind<G, B>): Kind<G, Validated<E, B>> = GA.run {
fix().fold({ e -> just(Invalid(e)) }, { a -> f(a).map(::Valid) })
}
fun <G, E, A, B> ValidatedOf<E, A>.traverse(GA: Applicative<G>, f: (A) -> Kind<G, B>): Kind<G, Validated<E, B>> =
GA.run {
fix().fold({ e -> just(Invalid(e)) }, { a -> f(a).map(::Valid) })
}

@Deprecated("@extension kinded projected functions are deprecated. Replace with sequence or sequenceEither from arrow.core.*")
fun <G, E, A> ValidatedOf<E, Kind<G, A>>.sequence(GA: Applicative<G>): Kind<G, Validated<E, A>> =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,36 @@ import arrow.core.andThen
import arrow.core.left
import arrow.core.right

const val SelectiveDeprecation =
"""Selective typeclass is deprecated and will be removed in 0.13.0."""

@Deprecated(KindDeprecation)
interface Selective<F> : Applicative<F> {
fun <A, B> Kind<F, Either<A, B>>.select(f: Kind<F, (A) -> B>): Kind<F, B>

private fun Kind<F, Boolean>.selector(): Kind<F, Either<Unit, Unit>> =
map { bool -> if (bool) Unit.left() else Unit.right() }

@Deprecated(SelectiveDeprecation)
fun <A, B, C> Kind<F, Either<A, B>>.branch(fl: Kind<F, (A) -> C>, fr: Kind<F, (B) -> C>): Kind<F, C> {
val nested: Kind<F, Either<A, Either<B, Nothing>>> = map { it.map(::Left) }
val ffl: Kind<F, (A) -> Either<Nothing, C>> = fl.map { it.andThen(::Right) }
return nested.select(ffl).select(fr)
}

@Deprecated(SelectiveDeprecation)
fun <A> Kind<F, Boolean>.whenS(x: Kind<F, () -> Unit>): Kind<F, Unit> =
selector().select(x.map { f -> { _: Unit -> f() } })

@Deprecated(SelectiveDeprecation)
fun <A> Kind<F, Boolean>.ifS(fl: Kind<F, A>, fr: Kind<F, A>): Kind<F, A> =
selector().branch(fl.map { { _: Unit -> it } }, fr.map { { _: Unit -> it } })

@Deprecated(SelectiveDeprecation)
fun <A> Kind<F, Boolean>.orS(f: Kind<F, Boolean>): Kind<F, Boolean> =
ifS(just(true), f)

@Deprecated(SelectiveDeprecation)
fun <A> Kind<F, Boolean>.andS(f: Kind<F, Boolean>): Kind<F, Boolean> =
ifS(f, just(false))
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class AndThenTest : UnitSpec() {
init {

testLaws(
MonadLaws.laws(AndThen.monad(), AndThen.functor(), AndThen.applicative(), AndThen.monad(), AndThen.genK(), AndThen.eqK<Int>()),
MonadLaws.laws(AndThen.monad(), AndThen.functor(), AndThen.applicative(), AndThen.genK(), AndThen.eqK<Int>()),
MonoidLaws.laws(AndThen.monoid<Int, Int>(Int.monoid()), Gen.int().map { i -> AndThen<Int, Int> { i } }, EQ),
ContravariantLaws.laws(AndThen.contravariant(), conestedGENK(), conestedEQK),
ProfunctorLaws.laws(AndThen.profunctor(), AndThen.genK2(), AndThen.eqK2()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import arrow.core.extensions.either.eqK.eqK
import arrow.core.extensions.either.eqK2.eqK2
import arrow.core.extensions.either.functor.functor
import arrow.core.extensions.either.hash.hash
import arrow.core.extensions.either.monad.monad
import arrow.core.extensions.either.monadError.monadError
import arrow.core.extensions.either.monoid.monoid
import arrow.core.extensions.either.order.order
Expand Down Expand Up @@ -74,7 +73,6 @@ class EitherTest : UnitSpec() {
Either.monadError(),
Either.functor(),
Either.applicative(),
Either.monad(),
Either.genK(Gen.throwable()),
Either.eqK(throwableEQ)
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class EvalTest : UnitSpec() {
init {

testLaws(
BimonadLaws.laws(Eval.bimonad(), Eval.monad(), Eval.comonad(), Eval.functor(), Eval.applicative(), Eval.monad(), GENK, EQK),
BimonadLaws.laws(Eval.bimonad(), Eval.monad(), Eval.comonad(), Eval.functor(), Eval.applicative(), GENK, EQK),
FxLaws.suspended<EvalEffect<*>, Eval<Int>, Int>(Gen.int().map(Eval.Companion::now), Gen.int().map(Eval.Companion::now), Eq.any(), eval::invoke) {
it.bind()
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ class IorTest : UnitSpec() {
Ior.monad(Int.semigroup()),
Ior.functor(),
Ior.applicative(Int.semigroup()),
Ior.monad(Int.semigroup()),
Ior.genK(Gen.int()),
Ior.eqK(Int.eq())
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import arrow.core.extensions.listk.eqK.eqK
import arrow.core.extensions.listk.foldable.foldable
import arrow.core.extensions.listk.functor.functor
import arrow.core.extensions.listk.hash.hash
import arrow.core.extensions.listk.monad.monad
import arrow.core.extensions.listk.monadCombine.monadCombine
import arrow.core.extensions.listk.monadLogic.monadLogic
import arrow.core.extensions.listk.monoid.monoid
Expand All @@ -24,7 +23,6 @@ import arrow.core.extensions.listk.traverse.traverse
import arrow.core.extensions.listk.unalign.unalign
import arrow.core.extensions.listk.unzip.unzip
import arrow.core.extensions.order
import arrow.core.extensions.option.eq.eq
import arrow.core.extensions.show
import arrow.core.test.UnitSpec
import arrow.core.test.generators.genK
Expand Down Expand Up @@ -62,7 +60,6 @@ class ListKTest : UnitSpec() {
ListK.monadCombine(),
ListK.functor(),
ListK.applicative(),
ListK.monad(),
ListK.genK(),
ListK.eqK()
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ class NonEmptyListTest : UnitSpec() {
NonEmptyList.comonad(),
NonEmptyList.functor(),
NonEmptyList.applicative(),
NonEmptyList.monad(),
NonEmptyList.genK(),
NonEmptyList.eqK()
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import arrow.core.extensions.option.monoid.monoid
import arrow.core.extensions.option.monoidal.monoidal
import arrow.core.extensions.option.order.order
import arrow.core.extensions.option.repeat.repeat
import arrow.core.extensions.option.selective.selective
import arrow.core.extensions.option.show.show
import arrow.core.extensions.option.traverseFilter.traverseFilter
import arrow.core.extensions.option.unalign.unalign
Expand Down Expand Up @@ -75,7 +74,6 @@ class OptionTest : UnitSpec() {
Option.monadCombine(),
Option.functor(),
Option.applicative(),
Option.selective(),
Option.genK(),
Option.eqK()
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import arrow.core.extensions.sequencek.foldable.foldable
import arrow.core.extensions.sequencek.functor.functor
import arrow.core.extensions.sequencek.functorFilter.functorFilter
import arrow.core.extensions.sequencek.hash.hash
import arrow.core.extensions.sequencek.monad.monad
import arrow.core.extensions.sequencek.monadCombine.monadCombine
import arrow.core.extensions.sequencek.monadLogic.monadLogic
import arrow.core.extensions.sequencek.monoidK.monoidK
Expand Down Expand Up @@ -63,7 +62,6 @@ class SequenceKTest : UnitSpec() {
SequenceK.monadCombine(),
SequenceK.functor(),
SequenceK.applicative(),
SequenceK.monad(),
SequenceK.genK(),
SequenceK.eqK()
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,8 @@ import arrow.core.extensions.validated.bitraverse.bitraverse
import arrow.core.extensions.validated.eq.eq
import arrow.core.extensions.validated.eqK.eqK
import arrow.core.extensions.validated.eqK2.eqK2
import arrow.core.extensions.validated.functor.functor
import arrow.core.extensions.validated.hash.hash
import arrow.core.extensions.validated.order.order
import arrow.core.extensions.validated.selective.selective
import arrow.core.extensions.validated.semigroupK.semigroupK
import arrow.core.extensions.validated.show.show
import arrow.core.extensions.validated.traverse.traverse
Expand All @@ -33,7 +31,6 @@ import arrow.core.test.laws.EqLaws
import arrow.core.test.laws.FxLaws
import arrow.core.test.laws.HashLaws
import arrow.core.test.laws.OrderLaws
import arrow.core.test.laws.SelectiveLaws
import arrow.core.test.laws.SemigroupKLaws
import arrow.core.test.laws.ShowLaws
import arrow.core.test.laws.TraverseLaws
Expand Down Expand Up @@ -63,7 +60,6 @@ class ValidatedTest : UnitSpec() {
ShowLaws.laws(Validated.show(String.show(), Int.show()), EQ, Gen.validated(Gen.string(), Gen.int())),
HashLaws.laws(Validated.hash(String.hash(), Int.hash()), Gen.validated(Gen.string(), Gen.int()), EQ),
OrderLaws.laws(Validated.order(String.order(), Int.order()), Gen.validated(Gen.string(), Gen.int())),
SelectiveLaws.laws(Validated.selective(String.semigroup()), Validated.functor(), Validated.genK(Gen.string()), Validated.eqK(String.eq())),
TraverseLaws.laws(Validated.traverse(), Validated.applicative(String.semigroup()), Validated.genK(Gen.string()), Validated.eqK(String.eq())),
SemigroupKLaws.laws(
Validated.semigroupK(String.semigroup()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import arrow.typeclasses.Eq
import arrow.typeclasses.EqK
import arrow.typeclasses.Functor
import arrow.typeclasses.Monad
import arrow.typeclasses.Selective
import io.kotlintest.properties.Gen
import io.kotlintest.properties.forAll

Expand Down Expand Up @@ -52,11 +51,10 @@ object BimonadLaws {
CM: Comonad<F>,
FF: Functor<F>,
AP: Apply<F>,
SL: Selective<F>,
GENK: GenK<F>,
EQK: EqK<F>
): List<Law> =
MonadLaws.laws(M, FF, AP, SL, GENK, EQK) +
MonadLaws.laws(M, FF, AP, GENK, EQK) +
ComonadLaws.laws(CM, GENK, EQK) +
bimonadLaws(BF, EQK)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import arrow.typeclasses.Apply
import arrow.typeclasses.EqK
import arrow.typeclasses.Functor
import arrow.typeclasses.MonadCombine
import arrow.typeclasses.Selective

@Deprecated(KindDeprecation)
object MonadCombineLaws {
Expand All @@ -22,9 +21,8 @@ object MonadCombineLaws {
MCF: MonadCombine<F>,
FF: Functor<F>,
AP: Apply<F>,
SL: Selective<F>,
GENK: GenK<F>,
EQK: EqK<F>
): List<Law> =
MonadFilterLaws.laws(MCF, FF, AP, SL, GENK, EQK) + AlternativeLaws.laws(MCF, GENK, EQK)
MonadFilterLaws.laws(MCF, FF, AP, GENK, EQK) + AlternativeLaws.laws(MCF, GENK, EQK)
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import arrow.typeclasses.Eq
import arrow.typeclasses.EqK
import arrow.typeclasses.Functor
import arrow.typeclasses.MonadError
import arrow.typeclasses.Selective
import io.kotlintest.fail
import io.kotlintest.properties.Gen
import io.kotlintest.properties.forAll
Expand Down Expand Up @@ -45,11 +44,10 @@ object MonadErrorLaws {
M: MonadError<F, Throwable>,
FF: Functor<F>,
AP: Apply<F>,
SL: Selective<F>,
GENK: GenK<F>,
EQK: EqK<F>
): List<Law> =
MonadLaws.laws(M, FF, AP, SL, GENK, EQK) +
MonadLaws.laws(M, FF, AP, GENK, EQK) +
ApplicativeErrorLaws.laws(M, GENK, EQK) +
monadErrorLaws(M, EQK)

Expand Down

0 comments on commit 497a4c0

Please sign in to comment.