Skip to content
This repository has been archived by the owner on Feb 24, 2021. It is now read-only.

Move instances to typeclass #287

Merged
merged 8 commits into from
Jan 12, 2021
Merged
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
38 changes: 19 additions & 19 deletions arrow-core-data/src/main/kotlin/arrow/core/Either.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1254,25 +1254,6 @@ sealed class Either<out A, out B> : EitherOf<A, B> {
fun <A, B, C, D> lift(fa: (A) -> C, fb: (B) -> D): (Either<A, B>) -> Either<C, D> =
{ it.bimap(fa, fb) }

/** Construct an [Eq] instance which use [EQL] and [EQR] to compare the [Left] and [Right] cases **/
fun <L, R> eq(EQL: Eq<L>, EQR: Eq<R>): Eq<Either<L, R>> =
EitherEq(EQL, EQR)

fun <A, B> hash(HA: Hash<A>, HB: Hash<B>): Hash<Either<A, B>> =
EitherHash(HA, HB)

fun <A, B> show(SA: Show<A>, SB: Show<B>): Show<Either<A, B>> =
EitherShow(SA, SB)

fun <A, B> order(OA: Order<A>, OB: Order<B>): Order<Either<A, B>> =
EitherOrder(OA, OB)

fun <A, B> semigroup(SA: Semigroup<A>, SB: Semigroup<B>): Semigroup<Either<A, B>> =
EitherSemigroup(SA, SB)

fun <A, B> monoid(MA: Monoid<A>, MB: Monoid<B>): Monoid<Either<A, B>> =
EitherMonoid(MA, MB)

inline fun <A, B, C, D> mapN(
b: Either<A, B>,
c: Either<A, C>,
Expand Down Expand Up @@ -1539,6 +1520,25 @@ fun <L> Left(left: L): Either<L, Nothing> = Left(left)

fun <R> Right(right: R): Either<Nothing, R> = Right(right)

/** Construct an [Eq] instance which use [EQL] and [EQR] to compare the [Left] and [Right] cases **/
fun <L, R> Eq.Companion.either(EQL: Eq<L>, EQR: Eq<R>): Eq<Either<L, R>> =
EitherEq(EQL, EQR)

fun <A, B> Hash.Companion.either(HA: Hash<A>, HB: Hash<B>): Hash<Either<A, B>> =
EitherHash(HA, HB)

fun <A, B> Show.Companion.either(SA: Show<A>, SB: Show<B>): Show<Either<A, B>> =
EitherShow(SA, SB)

fun <A, B> Order.Companion.either(OA: Order<A>, OB: Order<B>): Order<Either<A, B>> =
EitherOrder(OA, OB)

fun <A, B> Semigroup.Companion.either(SA: Semigroup<A>, SB: Semigroup<B>): Semigroup<Either<A, B>> =
EitherSemigroup(SA, SB)

fun <A, B> Monoid.Companion.either(MA: Monoid<A>, MB: Monoid<B>): Monoid<Either<A, B>> =
EitherMonoid(MA, MB)

/**
* Binds the given function across [Either.Right].
*
Expand Down
8 changes: 0 additions & 8 deletions arrow-core-data/src/main/kotlin/arrow/core/Iterable.kt
Original file line number Diff line number Diff line change
Expand Up @@ -678,14 +678,6 @@ fun <A, B> Iterable<A>.foldMap(MB: Monoid<B>, f: (A) -> B): B = MB.run {
}
}

fun <A> listEq(EQA: Eq<A>): Eq<List<A>> =
ListEq(EQA)

private class ListEq<A>(private val EQA: Eq<A>) : Eq<List<A>> {
override fun List<A>.eqv(b: List<A>): Boolean =
eqv(EQA, b)
}

fun <A> Iterable<A>.eqv(EQA: Eq<A>, other: Iterable<A>): Boolean = EQA.run {
if (this is Collection<*> && other is Collection && this.size != other.size) false
else {
Expand Down
23 changes: 18 additions & 5 deletions arrow-core-data/src/main/kotlin/arrow/core/List.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
package arrow.core

import arrow.typeclasses.Eq
import arrow.typeclasses.Hash
import arrow.typeclasses.Monoid
import arrow.typeclasses.Order
import arrow.typeclasses.Semigroup
import arrow.typeclasses.Show
import arrow.typeclasses.defaultSalt
import arrow.typeclasses.hashWithSalt

fun <A> listHash(HA: Hash<A>): Hash<List<A>> =
fun <A> Eq.Companion.list(EQA: Eq<A>): Eq<List<A>> =
ListEq(EQA)

private class ListEq<A>(private val EQA: Eq<A>) : Eq<List<A>> {
override fun List<A>.eqv(b: List<A>): Boolean =
eqv(EQA, b)
}

fun <A> Hash.Companion.list(HA: Hash<A>): Hash<List<A>> =
ListHash(HA)

private class ListHash<A>(private val HA: Hash<A>) : Hash<List<A>> {
Expand All @@ -24,7 +34,7 @@ fun <A> List<A>.hashWithSalt(HA: Hash<A>, salt: Int): Int = HA.run {

fun <A> List<A>.compare(OA: Order<A>, b: List<A>): Ordering = OA.run {
align(b) { ior -> ior.fold({ GT }, { LT }, { a1, a2 -> a1.compare(a2) }) }
.fold(Ordering.monoid())
.fold(Monoid.ordering())
}

/**
Expand Down Expand Up @@ -97,22 +107,25 @@ fun <A> List<A>.min(OA: Order<A>, b: List<A>): List<A> =
fun <A> List<A>.sort(OA: Order<A>, b: List<A>): Tuple2<List<A>, List<A>> =
if (gte(OA, b)) Tuple2(this, b) else Tuple2(b, this)

fun <A> listOrder(OA: Order<A>): Order<List<A>> =
fun <A> Order.Companion.list(OA: Order<A>): Order<List<A>> =
ListOrder(OA)

private class ListOrder<A>(private val OA: Order<A>) : Order<List<A>> {
override fun List<A>.compare(b: List<A>): Ordering = compare(OA, b)
}

fun <A> listMonoid(): Monoid<List<A>> =
fun <A> Semigroup.Companion.list(): Semigroup<List<A>> =
Monoid.list()

fun <A> Monoid.Companion.list(): Monoid<List<A>> =
ListMonoid as Monoid<List<A>>

object ListMonoid : Monoid<List<Any?>> {
override fun empty(): List<Any?> = emptyList()
override fun List<Any?>.combine(b: List<Any?>): List<Any?> = this + b
}

fun <A> listShow(SA: Show<A>): Show<List<A>> =
fun <A> Show.Companion.list(SA: Show<A>): Show<List<A>> =
object : Show<List<A>> {
override fun List<A>.show(): String =
show(SA)
Expand Down
24 changes: 12 additions & 12 deletions arrow-core-data/src/main/kotlin/arrow/core/Ordering.kt
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,6 @@ sealed class Ordering {
0 -> EQ
else -> if (i < 0) LT else GT
}

fun eq(): Eq<Ordering> = OrderingEq

fun hash(): Hash<Ordering> = OrderingHash

fun monoid(): Monoid<Ordering> = OrderingMonoid

fun order(): Order<Ordering> = OrderingOrder

fun semigroup(): Semigroup<Ordering> = OrderingMonoid

fun show(): Show<Ordering> = OrderingShow
}
}

Expand All @@ -100,6 +88,18 @@ object EQ : Ordering()
fun Collection<Ordering>.combineAll(): Ordering =
if (isEmpty()) OrderingMonoid.empty() else reduce { a, b -> a.combine(b) }

fun Eq.Companion.ordering(): Eq<Ordering> = OrderingEq

fun Hash.Companion.ordering(): Hash<Ordering> = OrderingHash

fun Semigroup.Companion.ordering(): Semigroup<Ordering> = OrderingMonoid

fun Monoid.Companion.ordering(): Monoid<Ordering> = OrderingMonoid

fun Order.Companion.ordering(): Order<Ordering> = OrderingOrder

fun Show.Companion.ordering(): Show<Ordering> = OrderingShow

@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
private object OrderingEq : Eq<Ordering> {
override fun Ordering.eqv(b: Ordering): Boolean =
Expand Down
50 changes: 37 additions & 13 deletions arrow-core-data/src/main/kotlin/arrow/core/Validated.kt
Original file line number Diff line number Diff line change
Expand Up @@ -497,19 +497,6 @@ sealed class Validated<out E, out A> : ValidatedOf<E, A> {
e.nonFatalOrThrow().invalidNel()
}

/** Construct an [Eq] instance which use [EQE] and [EQA] to compare the [Invalid] and [Valid] cases **/
fun <E, A> eq(EQE: Eq<E>, EQA: Eq<A>): Eq<Validated<E, A>> =
ValidatedEq(EQE, EQA)

fun <E, A> hash(HE: Hash<E>, HA: Hash<A>): Hash<Validated<E, A>> =
ValidatedHash(HE, HA)

fun <E, A> show(SE: Show<E>, SA: Show<A>): Show<Validated<E, A>> =
ValidatedShow(SE, SA)

fun <E, A> order(OE: Order<E>, OA: Order<A>): Order<Validated<E, A>> =
ValidatedOrder(OE, OA)

/**
* Lifts a function `A -> B` to the [Validated] structure.
*
Expand Down Expand Up @@ -1039,6 +1026,25 @@ sealed class Validated<out E, out A> : ValidatedOf<E, A> {
fold(::Valid, ::Invalid)
}

/** Construct an [Eq] instance which use [EQE] and [EQA] to compare the [Invalid] and [Valid] cases **/
fun <E, A> Eq.Companion.validated(EQE: Eq<E>, EQA: Eq<A>): Eq<Validated<E, A>> =
ValidatedEq(EQE, EQA)

fun <E, A> Hash.Companion.validated(HE: Hash<E>, HA: Hash<A>): Hash<Validated<E, A>> =
ValidatedHash(HE, HA)

fun <E, A> Show.Companion.validated(SE: Show<E>, SA: Show<A>): Show<Validated<E, A>> =
ValidatedShow(SE, SA)

fun <E, A> Order.Companion.validated(OE: Order<E>, OA: Order<A>): Order<Validated<E, A>> =
ValidatedOrder(OE, OA)

fun <E, A> Semigroup.Companion.validated(SE: Semigroup<E>, SA: Semigroup<A>): Semigroup<Validated<E, A>> =
ValidatedSemigroup(SE, SA)

fun <E, A> Semigroup.Companion.monoid(SE: Semigroup<E>, MA: Monoid<A>): Monoid<Validated<E, A>> =
ValidatedMonoid(SE, MA)

/**
* Compares two instances of [Validated] and returns true if they're considered not equal for this instance.
*
Expand Down Expand Up @@ -1421,3 +1427,21 @@ private class ValidatedOrder<L, R>(
override fun Validated<L, R>.compare(b: Validated<L, R>): Ordering =
compare(OL, OR, b)
}

private open class ValidatedSemigroup<A, B>(
private val SA: Semigroup<A>,
private val SB: Semigroup<B>
) : Semigroup<Validated<A, B>> {
override fun Validated<A, B>.combine(b: Validated<A, B>): Validated<A, B> =
combine(SA, SB, b)
}

private class ValidatedMonoid<A, B>(
private val SA: Semigroup<A>,
private val MB: Monoid<B>
) : Monoid<Validated<A, B>>, ValidatedSemigroup<A, B>(SA, MB) {
private val empty = Valid(MB.empty())

override fun empty(): Validated<A, B> =
empty
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ interface Semigroup<A> {
this.combine(b)

fun A.maybeCombine(b: A?): A = Option.fromNullable(b).fold({ this }, { combine(it) })

companion object
}
5 changes: 3 additions & 2 deletions arrow-core-data/src/test/kotlin/arrow/core/IterableTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package arrow.core
import arrow.core.extensions.eq
import arrow.core.test.UnitSpec
import arrow.core.test.laws.equalUnderTheLaw
import arrow.typeclasses.Eq
import io.kotlintest.properties.Gen
import io.kotlintest.properties.forAll
import kotlin.math.max
Expand Down Expand Up @@ -62,7 +63,7 @@ class IterableTest : UnitSpec() {
val result = a.rightPadZip(b)

result == left.zip(right) { l, r -> l toT r }.filter { it.a != null } &&
result.map { it.a }.equalUnderTheLaw(a, listEq(Int.eq()))
result.map { it.a }.equalUnderTheLaw(a, Eq.list(Int.eq()))
}
}

Expand All @@ -74,7 +75,7 @@ class IterableTest : UnitSpec() {
val result = a.rightPadZip(b) { a, b -> a toT b }

result == left.zip(right) { l, r -> l toT r }.filter { it.a != null } &&
result.map { it.a }.equalUnderTheLaw(a, listEq(Int.eq()))
result.map { it.a }.equalUnderTheLaw(a, Eq.list(Int.eq()))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fun <L, R> Either<L, R>.neqv(
"UNCHECKED_CAST",
"NOTHING_TO_INLINE"
)
@Deprecated("@extension projected functions are deprecated", ReplaceWith("Either.eq(EQL, EQR)", "arrow.core.eq"))
@Deprecated("@extension projected functions are deprecated", ReplaceWith("Eq.either(EQL, EQR)", "arrow.core.Eq", "arrow.core.either"))
inline fun <L, R> Companion.eq(EQL: Eq<L>, EQR: Eq<R>): EitherEq<L, R> = object :
arrow.core.extensions.EitherEq<L, R> {
override fun EQL(): arrow.typeclasses.Eq<L> = EQL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import kotlin.Suppress
"UNCHECKED_CAST",
"NOTHING_TO_INLINE"
)
@Deprecated("@extension kinded projected functions are deprecated", ReplaceWith("Either.hash(HL, HR)"))
@Deprecated("@extension kinded projected functions are deprecated", ReplaceWith("Hash.either(HL, HR)", "arrow.core.either", "arrow.core.Hash"))
inline fun <L, R> Companion.hash(HL: Hash<L>, HR: Hash<R>): EitherHash<L, R> = object :
arrow.core.extensions.EitherHash<L, R> {
override fun HL(): arrow.typeclasses.Hash<L> = HL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ fun <L, R> combineAll(
"UNCHECKED_CAST",
"NOTHING_TO_INLINE"
)
@Deprecated("@extension kinded projected functions are deprecated", ReplaceWith("Either.monoid(MOL, MOR)", "arrow.core.monoid"))
@Deprecated("@extension kinded projected functions are deprecated", ReplaceWith("Monoid.either(MOL, MOR)", "arrow.core.either", "arrow.core.Monoid"))
inline fun <L, R> Companion.monoid(MOL: Monoid<L>, MOR: Monoid<R>): EitherMonoid<L, R> = object :
arrow.core.extensions.EitherMonoid<L, R> {
override fun MOL(): arrow.typeclasses.Monoid<L> = MOL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ fun <L, R> Either<L, R>.sort(
"UNCHECKED_CAST",
"NOTHING_TO_INLINE"
)
@Deprecated("@extension kinded projected functions are deprecated", ReplaceWith("Either.order(OL, OR)", "arrow.core.order"))
@Deprecated("@extension kinded projected functions are deprecated", ReplaceWith("Order.either(OL, OR)", "arrow.core.Order", "arrow.core.either"))
inline fun <L, R> Companion.order(OL: Order<L>, OR: Order<R>): EitherOrder<L, R> = object :
arrow.core.extensions.EitherOrder<L, R> {
override fun OL(): arrow.typeclasses.Order<L> = OL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ fun <L, R> Either<L, R>.maybeCombine(
"UNCHECKED_CAST",
"NOTHING_TO_INLINE"
)
@Deprecated("@extension kinded projected functions are deprecated", ReplaceWith("Either.semigroup(SGL, SGR)", "arrow.core.semigroup"))
@Deprecated("@extension kinded projected functions are deprecated", ReplaceWith("Semigroup.either(SGL, SGR)", "arrow.core.Semigroup", "arrow.core.either"))
inline fun <L, R> Companion.semigroup(SGL: Semigroup<L>, SGR: Semigroup<R>): EitherSemigroup<L, R> =
object : arrow.core.extensions.EitherSemigroup<L, R> {
override fun SGL():
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import kotlin.Suppress
"UNCHECKED_CAST",
"NOTHING_TO_INLINE"
)
@Deprecated("@extension kinded projected functions are deprecated", ReplaceWith("Either.show(HL, HR)", "arrow.core.hash"))
@Deprecated("@extension kinded projected functions are deprecated", ReplaceWith("Show.either(HL, HR)", "arrow.core.Show", "arrow.core.either"))
inline fun <L, R> Companion.show(SL: Show<L>, SR: Show<R>): EitherShow<L, R> = object :
arrow.core.extensions.EitherShow<L, R> {
override fun SL(): arrow.typeclasses.Show<L> = SL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ object List {
"UNCHECKED_CAST",
"NOTHING_TO_INLINE"
)
@Deprecated("@extension projected functions are deprecated", ReplaceWith("listEq(EQ)", "arrow.core.listEq"))
@Deprecated("@extension projected functions are deprecated", ReplaceWith("Eq.list(EQ)", "arrow.core.list", "arrow.core.Eq"))
inline fun <A> eq(EQ: Eq<A>): ListKEq<A> = object : arrow.core.extensions.ListKEq<A> { override
fun EQ(): arrow.typeclasses.Eq<A> = EQ }}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ object List {
"UNCHECKED_CAST",
"NOTHING_TO_INLINE"
)
@Deprecated("@extension projected functions are deprecated", ReplaceWith("listHash(HA)", "arrow.core.listHash"))
@Deprecated("@extension projected functions are deprecated", ReplaceWith("Hash.list(HA)", "arrow.core.list", "arrow.core.Hash"))
inline fun <A> hash(HA: Hash<A>): ListKHash<A> = object : arrow.core.extensions.ListKHash<A> {
override fun HA(): arrow.typeclasses.Hash<A> = HA }}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,6 @@ object List {
"UNCHECKED_CAST",
"NOTHING_TO_INLINE"
)
@Deprecated("@extension projected functions are deprecated", ReplaceWith("listMonoid<A>()", "arrow.core.listMonoid"))
@Deprecated("@extension projected functions are deprecated", ReplaceWith("Monoid.list<A>()", "arrow.core.list", "arrow.core.Monoid"))
inline fun <A> monoid(): ListKMonoid<A> = monoid_singleton as
arrow.core.extensions.ListKMonoid<A>}
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,6 @@ object List {
"UNCHECKED_CAST",
"NOTHING_TO_INLINE"
)
@Deprecated("@extension projected functions are deprecated", ReplaceWith("listOrder(OA)", "arrow.core.listOrder"))
@Deprecated("@extension projected functions are deprecated", ReplaceWith("Order.list(OA)", "arrow.core.list", "arrow.core.Order"))
inline fun <A> order(OA: Order<A>): ListKOrder<A> = object : arrow.core.extensions.ListKOrder<A> {
override fun OA(): arrow.typeclasses.Order<A> = OA }}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,6 @@ object List {
"UNCHECKED_CAST",
"NOTHING_TO_INLINE"
)
@Deprecated("@extension projected functions are deprecated", ReplaceWith("listMonoid<A>()", "arrow.core.listMonoid"))
@Deprecated("@extension projected functions are deprecated", ReplaceWith("Semigroup.list<A>()", "arrow.core.list", "arrow.core.Semigroup"))
inline fun <A> semigroup(): ListKSemigroup<A> = semigroup_singleton as
arrow.core.extensions.ListKSemigroup<A>}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ object List {
"UNCHECKED_CAST",
"NOTHING_TO_INLINE"
)
@Deprecated("@extension projected functions are deprecated", ReplaceWith("listShow(arg1)", "arrow.core.listShow"))
@Deprecated("@extension projected functions are deprecated", ReplaceWith("Show.list(arg1)", "arrow.core.list", "arrow.core.Show"))
inline fun <A> show(SA: Show<A>): ListKShow<A> = object : arrow.core.extensions.ListKShow<A> {
override fun SA(): arrow.typeclasses.Show<A> = SA }}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ fun <A> Kind<ForListK, A>.neqv(EQ: Eq<A>, arg1: Kind<ForListK, A>): Boolean =
"UNCHECKED_CAST",
"NOTHING_TO_INLINE"
)
@Deprecated("@extension projected functions are deprecated", ReplaceWith("listEq(EQ)", "arrow.core.listEq"))
@Deprecated("@extension projected functions are deprecated", ReplaceWith("Eq.list(EQ)", "arrow.core.list", "arrow.core.Eq"))
inline fun <A> Companion.eq(EQ: Eq<A>): ListKEq<A> = object : arrow.core.extensions.ListKEq<A> {
override fun EQ(): arrow.typeclasses.Eq<A> = EQ }
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ fun <A> Kind<ForListK, A>.hashWithSalt(HA: Hash<A>, arg1: Int): Int =
"UNCHECKED_CAST",
"NOTHING_TO_INLINE"
)
@Deprecated("@extension projected functions are deprecated", ReplaceWith("listHash(HA)", "arrow.core.listHash"))
@Deprecated("@extension projected functions are deprecated", ReplaceWith("Hash.list(HA)", "arrow.core.list", "arrow.core.Hash"))
inline fun <A> Companion.hash(HA: Hash<A>): ListKHash<A> = object :
arrow.core.extensions.ListKHash<A> { override fun HA(): arrow.typeclasses.Hash<A> = HA }
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,6 @@ fun <A> combineAll(arg0: List<ListK<A>>): ListK<A> = arrow.core.ListK
"UNCHECKED_CAST",
"NOTHING_TO_INLINE"
)
@Deprecated("@extension projected functions are deprecated", ReplaceWith("listMonoid<A>()", "arrow.core.listMonoid"))
@Deprecated("@extension projected functions are deprecated", ReplaceWith("Monoid.list<A>()", "arrow.core.list", "arrow.core.Monoid"))
inline fun <A> Companion.monoid(): ListKMonoid<A> = monoid_singleton as
arrow.core.extensions.ListKMonoid<A>