Skip to content

Commit 01bdd2a

Browse files
authored
Merge pull request #125 from kategory/paco-eqclean
Extract common implementations of Eq
2 parents 1f1b1cc + db8b249 commit 01bdd2a

21 files changed

+56
-36
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package kategory
2+
3+
class EvalEq : Eq<HK<Eval.F, Int>> {
4+
override fun eqv(a: HK<Eval.F, Int>, b: HK<Eval.F, Int>): Boolean =
5+
a.ev().value() == b.ev().value()
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package kategory
2+
3+
data class FreeEq<in F, in G, in A>(private val interpreter: FunctionK<F, G>, private val MG: Monad<G>) : Eq<HK<FreeF<F>, A>> {
4+
override fun eqv(a: HK<FreeF<F>, A>, b: HK<FreeF<F>, A>): Boolean =
5+
a.ev().foldMap(interpreter, MG) == b.ev().foldMap(interpreter, MG)
6+
7+
companion object {
8+
inline operator fun <F, reified G, A> invoke(interpreter: FunctionK<F, G>, MG: Monad<G> = monad(), dummy: Unit = Unit): FreeEq<F, G, A> =
9+
FreeEq(interpreter, MG)
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package kategory
2+
3+
class Function0Eq : Eq<HK<Function0.F, Int>> {
4+
override fun eqv(a: HK<Function0.F, Int>, b: HK<Function0.F, Int>): Boolean =
5+
a.ev()() == b.ev()()
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package kategory
2+
3+
class IOEq : Eq<HK<IO.F, Int>> {
4+
override fun eqv(a: HK<IO.F, Int>, b: HK<IO.F, Int>): Boolean =
5+
a.ev().unsafeRunSync() == b.ev().unsafeRunSync()
6+
}

kategory/src/main/kotlin/kategory/typeclasses/Eq.kt

+6-3
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@ interface Eq<in F> : Typeclass {
77
!eqv(a, b)
88

99
companion object {
10-
operator fun <F> invoke() = object : Eq<F> {
11-
override fun eqv(a: F, b: F): Boolean =
10+
fun any(): Eq<Any?> =
11+
EqAny()
12+
13+
private class EqAny : Eq<Any?> {
14+
override fun eqv(a: Any?, b: Any?): Boolean =
1215
a == b
1316

14-
override fun neqv(a: F, b: F): Boolean =
17+
override fun neqv(a: Any?, b: Any?): Boolean =
1518
a != b
1619
}
1720
}

kategory/src/test/kotlin/kategory/data/EitherTTest.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import org.junit.runner.RunWith
1010
class EitherTTest : UnitSpec() {
1111
init {
1212

13-
testLaws(MonadLaws.laws(EitherTMonad<Id.F, Int>(), Eq()))
13+
testLaws(MonadLaws.laws(EitherTMonad<Id.F, Int>(), Eq.any()))
1414

1515
"map should modify value" {
1616
forAll { a: String ->
@@ -182,7 +182,7 @@ class EitherTTest : UnitSpec() {
182182
forAll(Gen.oneOf(listOf(10000))) { limit: Int ->
183183
val value: EitherT<Id.F, Int, Int> = EitherTMonad<Id.F, Int>(Id).tailRecM(0) { current ->
184184
if (current == limit)
185-
EitherT.left<Id.F, Int, Either<Int, Int>>(current)
185+
EitherT.left(current)
186186
else
187187
EitherT.pure<Id.F, Int, Either<Int, Int>>(Either.Left(current + 1))
188188
}

kategory/src/test/kotlin/kategory/data/EitherTest.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import org.junit.runner.RunWith
1111
class EitherTest : UnitSpec() {
1212
init {
1313

14-
testLaws(MonadErrorLaws.laws(EitherMonadError<Throwable>(), Eq()))
14+
testLaws(MonadErrorLaws.laws(EitherMonadError(), Eq.any()))
1515

1616
"map should modify value" {
1717
forAll { a: Int, b: String ->

kategory/src/test/kotlin/kategory/data/EvalTest.kt

+1-4
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@ import org.junit.runner.RunWith
88
class EvalTest : UnitSpec() {
99
init {
1010

11-
testLaws(MonadLaws.laws(Eval, object : Eq<HK<Eval.F, Int>> {
12-
override fun eqv(a: HK<Eval.F, Int>, b: HK<Eval.F, Int>): Boolean =
13-
a.ev().value() == b.ev().value()
14-
}))
11+
testLaws(MonadLaws.laws(Eval, EvalEq()))
1512

1613
"should map wrapped value" {
1714
val sideEffect = SideEffect()

kategory/src/test/kotlin/kategory/data/Function0Test.kt

+1-4
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@ import org.junit.runner.RunWith
88
class Function0Test : UnitSpec() {
99
init {
1010

11-
testLaws(MonadLaws.laws(Function0, object : Eq<HK<Function0.F, Int>> {
12-
override fun eqv(a: HK<Function0.F, Int>, b: HK<Function0.F, Int>): Boolean =
13-
a.ev()() == b.ev()()
14-
}))
11+
testLaws(MonadLaws.laws(Function0, Function0Eq()))
1512

1613
"Function0Monad.binding should for comprehend over all values of multiple Function0" {
1714
Function0.binding {

kategory/src/test/kotlin/kategory/data/IdTest.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import org.junit.runner.RunWith
88
class IdTest : UnitSpec() {
99
init {
1010

11-
testLaws(MonadLaws.laws(Id, Eq()))
11+
testLaws(MonadLaws.laws(Id, Eq.any()))
1212

1313
"IdMonad.binding should for comprehend over all values of multiple Ids" {
1414
Id.binding {

kategory/src/test/kotlin/kategory/data/IorTest.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class IorTest : UnitSpec() {
1313

1414
val intIorMonad = IorMonad(IntMonoid)
1515

16-
testLaws(MonadLaws.laws(intIorMonad, Eq()))
16+
testLaws(MonadLaws.laws(intIorMonad, Eq.any()))
1717

1818
"flatMap() should modify entity" {
1919
forAll { a: Int, b: String ->

kategory/src/test/kotlin/kategory/data/NonEmptyListTest.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import org.junit.runner.RunWith
99
class NonEmptyListTest : UnitSpec() {
1010
init {
1111

12-
testLaws(MonadLaws.laws(NonEmptyList, Eq()))
12+
testLaws(MonadLaws.laws(NonEmptyList, Eq.any()))
1313

1414
"map should modify values" {
1515
NonEmptyList.of(14).map { it * 3 } shouldBe NonEmptyList.of(42)

kategory/src/test/kotlin/kategory/data/OptionTTest.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import org.junit.runner.RunWith
99
class OptionTTest : UnitSpec() {
1010
init {
1111

12-
testLaws(MonadLaws.laws(OptionTMonad(NonEmptyList), Eq()))
12+
testLaws(MonadLaws.laws(OptionTMonad(NonEmptyList), Eq.any()))
1313

1414
"map should modify value" {
1515
forAll { a: String ->

kategory/src/test/kotlin/kategory/data/OptionTest.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class OptionTest: UnitSpec() {
1313

1414
init {
1515

16-
testLaws(MonadLaws.laws(Option, Eq()))
16+
testLaws(MonadLaws.laws(Option, Eq.any()))
1717

1818
"map should modify value" {
1919
Some(12).map { "flower" } shouldBe Some("flower")

kategory/src/test/kotlin/kategory/data/TryTest.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class TryTest : UnitSpec() {
1111

1212
init {
1313

14-
testLaws(MonadErrorLaws.laws(Try, Eq()))
14+
testLaws(MonadErrorLaws.laws(Try, Eq.any()))
1515

1616
"invoke of any should be success" {
1717
Try.invoke { 1 } shouldBe Success(1)

kategory/src/test/kotlin/kategory/data/ValidatedTest.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class ValidatedTest : UnitSpec() {
1616
override fun combine(a: String, b: String): String = "$a $b"
1717
}
1818

19-
testLaws(ApplicativeLaws.laws(ValidatedApplicativeError(concatStringSG), Eq()))
19+
testLaws(ApplicativeLaws.laws(ValidatedApplicativeError(concatStringSG), Eq.any()))
2020

2121
"fold should call function on Invalid" {
2222
val exception = Exception("My Exception")

kategory/src/test/kotlin/kategory/data/WriterTTest.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import org.junit.runner.RunWith
99
class WriterTTest : UnitSpec() {
1010
init {
1111

12-
testLaws(MonadLaws.laws(WriterTMonad(NonEmptyList, IntMonoid), Eq()))
12+
testLaws(MonadLaws.laws(WriterTMonad(NonEmptyList, IntMonoid), Eq.any()))
1313

1414
"tell should accumulate write" {
1515
forAll { a: Int ->

kategory/src/test/kotlin/kategory/effects/IOTest.kt

+1-4
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,7 @@ class IOTest : UnitSpec() {
1111

1212
init {
1313

14-
testLaws(MonadLaws.laws(IO, object : Eq<HK<IO.F, Int>> {
15-
override fun eqv(a: HK<IO.F, Int>, b: HK<IO.F, Int>): Boolean =
16-
a.ev().unsafeRunSync() == b.ev().unsafeRunSync()
17-
}))
14+
testLaws(MonadLaws.laws(IO, IOEq()))
1815

1916
"should defer evaluation until run" {
2017
var run = false

kategory/src/test/kotlin/kategory/free/FreeTest.kt

+4-7
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,21 @@ fun <A> HK<Ops.F, A>.ev(): Ops<A> = this as Ops<A>
2424
@RunWith(KTestJUnitRunner::class)
2525
class FreeTest : UnitSpec() {
2626

27-
val program = Ops.binding {
27+
private val program = Ops.binding {
2828
val added = !Ops.add(10, 10)
2929
val subtracted = !Ops.subtract(added, 50)
3030
yields(subtracted)
3131
}.ev()
3232

33-
fun stackSafeTestProgram(n: Int, stopAt: Int): Free<Ops.F, Int> = Ops.binding {
33+
private fun stackSafeTestProgram(n: Int, stopAt: Int): Free<Ops.F, Int> = Ops.binding {
3434
val v = !Ops.add(n, 1)
35-
val r = !if (v < stopAt) stackSafeTestProgram(v, stopAt) else Free.pure<Ops.F, Int>(v)
35+
val r = !if (v < stopAt) stackSafeTestProgram(v, stopAt) else Free.pure(v)
3636
yields(r)
3737
}.ev()
3838

3939
init {
4040

41-
testLaws(MonadLaws.laws(Ops, object : Eq<HK<FreeF<Ops.F>, Int>> {
42-
override fun eqv(a: HK<FreeF<Ops.F>, Int>, b: HK<FreeF<Ops.F>, Int>): Boolean =
43-
a.ev().foldMap(idInterpreter, Id) == b.ev().foldMap(idInterpreter, Id)
44-
}))
41+
testLaws(MonadLaws.laws(Ops, FreeEq(idInterpreter)))
4542

4643
"Can interpret an ADT as Free operations" {
4744
program.foldMap(optionInterpreter, Option).ev() shouldBe Option.Some(-30)

kategory/src/test/kotlin/kategory/laws/FunctorLaws.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ object FunctorLaws {
1111
Law("Functor: Covariant Composition", { covariantComposition(AP, EQ) })
1212
)
1313

14-
inline fun <reified F> covariantIdentity(AP: Applicative<F> = applicative<F>(), EQ: Eq<HK<F, Int>> = Eq()): Unit =
14+
inline fun <reified F> covariantIdentity(AP: Applicative<F> = applicative<F>(), EQ: Eq<HK<F, Int>> = Eq.any()): Unit =
1515
forAll(genApplicative(Gen.int(), AP), { fa: HK<F, Int> ->
1616
AP.map(fa, ::identity).equalUnderTheLaw(fa, EQ)
1717
})
1818

19-
inline fun <reified F> covariantComposition(AP: Applicative<F> = applicative<F>(), EQ: Eq<HK<F, Int>> = Eq()): Unit =
19+
inline fun <reified F> covariantComposition(AP: Applicative<F> = applicative<F>(), EQ: Eq<HK<F, Int>> = Eq.any()): Unit =
2020
forAll(
2121
genApplicative(Gen.int(), AP),
2222
genFunctionAToB<Int, Int>(Gen.int()),

kategory/src/test/kotlin/kategory/laws/Law.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ package kategory
22

33
data class Law(val name: String, val test: () -> Unit)
44

5-
inline fun <reified A> A.equalUnderTheLaw(b: A, eq: Eq<A> = Eq()): Boolean =
5+
inline fun <reified A> A.equalUnderTheLaw(b: A, eq: Eq<A> = Eq.any()): Boolean =
66
eq.eqv(this, b)

0 commit comments

Comments
 (0)