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

Add InvariantSemigroupal and ability to turn Monoidals to Monoids #2088

Merged
merged 24 commits into from
Dec 18, 2017
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,26 @@ def mimaSettings(moduleName: String) = Seq(
exclude[DirectMissingMethodProblem]("cats.data.RWSTAlternative.sequence"),
exclude[ReversedMissingMethodProblem]("cats.MonadError.rethrow"),
exclude[ReversedMissingMethodProblem]("cats.syntax.MonadErrorSyntax.catsSyntaxMonadErrorRethrow"),
exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.composeApply"),
exclude[DirectMissingMethodProblem]("cats.Semigroupal.catsSemigroupalForMonoid"),
exclude[ReversedMissingMethodProblem]("cats.instances.InvariantMonoidalInstances.catsSemigroupalForMonoid"),
exclude[DirectMissingMethodProblem]("cats.implicits.catsContravariantSemigroupalForPartialOrder"),
exclude[DirectMissingMethodProblem]("cats.instances.PartialOrderingInstances.catsContravariantSemigroupalForPartialOrdering"),
exclude[ReversedMissingMethodProblem]("cats.instances.PartialOrderingInstances.catsContravariantMonoidalForPartialOrdering"),
exclude[DirectMissingMethodProblem]("cats.instances.package#partialOrdering.catsContravariantSemigroupalForPartialOrdering"),
exclude[DirectMissingMethodProblem]("cats.instances.package#all.catsContravariantSemigroupalForPartialOrder"),
exclude[DirectMissingMethodProblem]("cats.instances.package#all.catsContravariantSemigroupalForPartialOrdering"),
exclude[DirectMissingMethodProblem]("cats.data.ConstInstances1.catsConstInvariantMonoidal"),
exclude[ReversedMissingMethodProblem]("cats.instances.PartialOrderInstances.cats$instances$PartialOrderInstances$_setter_$catsContravariantMonoidalForPartialOrder_="),
exclude[ReversedMissingMethodProblem]("cats.instances.PartialOrderingInstances.cats$instances$PartialOrderingInstances$_setter_$catsContravariantMonoidalForPartialOrdering_="),
exclude[DirectMissingMethodProblem]("cats.instances.package#partialOrder.catsContravariantSemigroupalForPartialOrder"),
exclude[DirectMissingMethodProblem]("cats.instances.PartialOrderInstances.catsContravariantSemigroupalForPartialOrder"),
exclude[ReversedMissingMethodProblem]("cats.instances.PartialOrderInstances.catsContravariantMonoidalForPartialOrder"),
exclude[DirectMissingMethodProblem]("cats.implicits.catsContravariantSemigroupalForPartialOrdering"),
exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.point"),
exclude[DirectMissingMethodProblem]("cats.InvariantMonoidal.pure"),
exclude[ReversedMissingMethodProblem]("cats.InvariantMonoidal.point"),
exclude[ReversedMissingMethodProblem]("cats.InvariantMonoidal.unit"),
exclude[DirectMissingMethodProblem]("cats.data.CokleisliArrow.id"),
exclude[IncompatibleResultTypeProblem]("cats.data.CokleisliArrow.id"),
exclude[DirectMissingMethodProblem]("cats.Apply#Ops.followedBy"),
Expand Down
5 changes: 4 additions & 1 deletion core/src/main/scala/cats/Applicative.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import simulacrum.typeclass
*
* Must obey the laws defined in cats.laws.ApplicativeLaws.
*/
@typeclass trait Applicative[F[_]] extends Apply[F] { self =>
@typeclass trait Applicative[F[_]] extends Apply[F] with InvariantMonoidal[F] { self =>



/**
* `pure` lifts any value into the Applicative Functor.
Expand Down Expand Up @@ -184,6 +186,7 @@ import simulacrum.typeclass
*/
def whenA[A](cond: Boolean)(f: => F[A]): F[Unit] =
if (cond) void(f) else pure(())

}

object Applicative {
Expand Down
3 changes: 2 additions & 1 deletion core/src/main/scala/cats/Apply.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import simulacrum.noop
* Must obey the laws defined in cats.laws.ApplyLaws.
*/
@typeclass(excludeParents = List("ApplyArityFunctions"))
trait Apply[F[_]] extends Functor[F] with Semigroupal[F] with ApplyArityFunctions[F] { self =>
trait Apply[F[_]] extends Functor[F] with InvariantSemigroupal[F] with ApplyArityFunctions[F] { self =>

/**
* Given a value and a function in the Apply context, applies the
Expand Down Expand Up @@ -94,6 +94,7 @@ trait Apply[F[_]] extends Functor[F] with Semigroupal[F] with ApplyArityFunction
val F = self
val G = Apply[G]
}

}

object Apply {
Expand Down
14 changes: 13 additions & 1 deletion core/src/main/scala/cats/Composed.scala
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ private[cats] trait ComposedApplicativeContravariantMonoidal[F[_], G[_]] extends
def F: Applicative[F]
def G: ContravariantMonoidal[G]

override def unit[A]: F[G[A]] = F.pure(G.unit)
override def unit: F[G[Unit]] = F.pure(G.unit)

override def contramap[A, B](fa: F[G[A]])(f: B => A): F[G[B]] =
F.map(fa)(G.contramap(_)(f))
Expand All @@ -144,6 +144,18 @@ private[cats] trait ComposedSemigroupal[F[_], G[_]] extends ContravariantSemigro
}
}

private[cats] trait ComposedInvariantApplySemigroupal[F[_], G[_]] extends InvariantSemigroupal[λ[α => F[G[α]]]] with ComposedInvariantCovariant[F, G] { outer =>
def F: InvariantSemigroupal[F]
def G: Apply[G]

def product[A, B](fa: F[G[A]], fb: F[G[B]]): F[G[(A, B)]] =
F.imap(F.product(fa, fb)) { case (ga, gb) =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you plan to add tests for this instance?

G.map2(ga, gb)(_ -> _)
} { g: G[(A, B)] =>
(G.map(g)(_._1), G.map(g)(_._2))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is not tested, we might need to test an instance that is not a covariant.

}
}

private[cats] trait ComposedCovariantContravariant[F[_], G[_]] extends Contravariant[λ[α => F[G[α]]]] { outer =>
def F: Functor[F]
def G: Contravariant[G]
Expand Down
16 changes: 12 additions & 4 deletions core/src/main/scala/cats/ContravariantMonoidal.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,20 @@ import simulacrum.typeclass
* Based on ekmett's contravariant library:
* https://hackage.haskell.org/package/contravariant-1.4/docs/Data-Functor-Contravariant-Divisible.html
*/
@typeclass trait ContravariantMonoidal[F[_]] extends ContravariantSemigroupal[F] { self =>
@typeclass trait ContravariantMonoidal[F[_]] extends ContravariantSemigroupal[F] with InvariantMonoidal[F] {
/**
* `unit` produces an instance of `F` for any type `A`
* `trivial` produces an instance of `F` for any type `A`
* that is trivial with respect to `contramap2` along
* the diagonal
*/
def unit[A]: F[A]
def trivial[A]: F[A] = contramap(unit)(_ => ())

}
object ContravariantMonoidal extends SemigroupalArityFunctions {
def monoid[F[_], A](implicit f: ContravariantMonoidal[F]): Monoid[F[A]] =
new ContravariantMonoidalMonoid[F, A](f)
}

private[cats] class ContravariantMonoidalMonoid[F[_], A](f: ContravariantMonoidal[F]) extends ContravariantSemigroupalSemigroup[F, A](f) with Monoid[F[A]] {
def empty: F[A] = f.trivial
}
object ContravariantMonoidal extends SemigroupalArityFunctions
14 changes: 12 additions & 2 deletions core/src/main/scala/cats/ContravariantSemigroupal.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,21 @@ import simulacrum.typeclass
* [[ContravariantSemigroupal]] is nothing more than something both contravariant
* and Semigroupal. It comes up enough to be useful, and composes well
*/
@typeclass trait ContravariantSemigroupal[F[_]] extends Semigroupal[F] with Contravariant[F] { self =>
@typeclass trait ContravariantSemigroupal[F[_]] extends InvariantSemigroupal[F] with Contravariant[F] { self =>
override def composeFunctor[G[_]: Functor]: ContravariantSemigroupal[λ[α => F[G[α]]]] =
new ComposedSemigroupal[F, G] {
def F = self
def G = Functor[G]
}

}

object ContravariantSemigroupal extends SemigroupalArityFunctions {
def semigroup[F[_], A](implicit f: ContravariantSemigroupal[F]): Semigroup[F[A]] =
new ContravariantSemigroupalSemigroup[F, A](f)
}

private[cats] class ContravariantSemigroupalSemigroup[F[_], A](f: ContravariantSemigroupal[F]) extends Semigroup[F[A]] {
def combine(a: F[A], b: F[A]): F[A] =
ContravariantSemigroupal.contramap2(a, b)((a: A) => (a, a))(f, f)
}
object ContravariantSemigroupal extends SemigroupalArityFunctions
32 changes: 30 additions & 2 deletions core/src/main/scala/cats/InvariantMonoidal.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,34 @@ import simulacrum.typeclass
*
* Must obey the laws defined in cats.laws.InvariantMonoidalLaws.
*/
@typeclass trait InvariantMonoidal[F[_]] extends Invariant[F] with Semigroupal[F] {
def pure[A](a: A): F[A]
@typeclass trait InvariantMonoidal[F[_]] extends InvariantSemigroupal[F] {
/**
* `point` lifts any value into a Monoidal Functor.
*
* Example:
* {{{
* scala> import cats.implicits._
*
* scala> InvariantMonoidal[Option].point(10)
* res0: Option[Int] = Some(10)
* }}}
*/
def point[A](a: A): F[A] = imap(unit)(_ => a)(_ => ())

def unit: F[Unit]


}

object InvariantMonoidal {
/**
* Gives a `Monoid` instance if A itself has a `Monoid` instance.
*/
def monoid[F[_], A](implicit F: InvariantMonoidal[F], A: Monoid[A]): Monoid[F[A]] =
new InvariantMonoidalMonoid[F, A](F, A)
}


private[cats] class InvariantMonoidalMonoid[F[_], A](f: InvariantMonoidal[F], monoid: Monoid[A]) extends InvariantSemigroupalSemigroup(f, monoid) with Monoid[F[A]] {
def empty: F[A] = f.point(monoid.empty)
}
30 changes: 30 additions & 0 deletions core/src/main/scala/cats/InvariantSemigroupal.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package cats

import simulacrum.typeclass

/**
* [[InvariantSemigroupal]] is nothing more than something both invariant
* and Semigroupal. It comes up enough to be useful, and composes well
*/
@typeclass trait InvariantSemigroupal[F[_]] extends Semigroupal[F] with Invariant[F] { self =>

def composeApply[G[_]: Apply]: InvariantSemigroupal[λ[α => F[G[α]]]] =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any plan to test cover this one as well?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Has this been addressed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep!

new ComposedInvariantApplySemigroupal[F, G] {
def F = self
def G = Apply[G]
}

}

object InvariantSemigroupal extends SemigroupalArityFunctions {
/**
* Gives a `Semigroup` instance if A itself has a `Semigroup` instance.
*/
def semigroup[F[_], A](implicit F: InvariantSemigroupal[F], A: Semigroup[A]): Semigroup[F[A]] =
new InvariantSemigroupalSemigroup[F, A](F, A)
}

private[cats] class InvariantSemigroupalSemigroup[F[_], A](f: InvariantSemigroupal[F], sg: Semigroup[A]) extends Semigroup[F[A]] {
def combine(a: F[A], b: F[A]): F[A] =
InvariantSemigroupal.imap2(a, b)(sg.combine)(a => (a, a))(f, f)
}
9 changes: 1 addition & 8 deletions core/src/main/scala/cats/Semigroupal.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,4 @@ import simulacrum.typeclass
def product[A, B](fa: F[A], fb: F[B]): F[(A, B)]
}

object Semigroupal extends SemigroupalArityFunctions {
implicit def catsSemigroupalForMonoid: Semigroupal[Monoid] = new Semigroupal[Monoid] {
def product[A, B](fa: Monoid[A], fb: Monoid[B]): Monoid[(A, B)] = new Monoid[(A, B)] {
val empty = fa.empty -> fb.empty
def combine(x: (A, B), y: (A, B)): (A, B) = fa.combine(x._1, y._1) -> fb.combine(x._2, y._2)
}
}
}
object Semigroupal extends SemigroupalArityFunctions
12 changes: 1 addition & 11 deletions core/src/main/scala/cats/data/Const.scala
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ private[data] sealed abstract class ConstInstances extends ConstInstances0 {
}

implicit def catsDataContravariantMonoidalForConst[D: Monoid]: ContravariantMonoidal[Const[D, ?]] = new ContravariantMonoidal[Const[D, ?]] {
override def unit[A] = Const.empty[D, A]
override def unit = Const.empty[D, Unit]
override def contramap[A, B](fa: Const[D, A])(f: B => A): Const[D, B] =
fa.retag[B]
override def product[A, B](fa: Const[D, A], fb: Const[D, B]): Const[D, (A, B)] =
Expand Down Expand Up @@ -135,16 +135,6 @@ private[data] sealed abstract class ConstInstances0 extends ConstInstances1 {
}

private[data] sealed abstract class ConstInstances1 {
implicit def catsConstInvariantMonoidal[C: Monoid]: InvariantMonoidal[Const[C, ?]] = new InvariantMonoidal[Const[C, ?]] {
def pure[A](a: A): Const[C, A] =
Const.empty

def imap[A, B](fa: Const[C, A])(f: A => B)(g: B => A): Const[C, B] =
fa.retag[B]

def product[A, B](fa: Const[C, A], fb: Const[C, B]): Const[C, (A, B)] =
fa.retag[(A, B)] combine fb.retag[(A, B)]
}

implicit def catsDataEqForConst[A: Eq, B]: Eq[Const[A, B]] = new Eq[Const[A, B]] {
def eqv(x: Const[A, B], y: Const[A, B]): Boolean =
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/data/IdT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ private[data] sealed trait IdTApplicative[F[_]] extends Applicative[IdT[F, ?]] w
private[data] sealed trait IdTContravariantMonoidal[F[_]] extends ContravariantMonoidal[IdT[F, ?]] {
implicit val F0: ContravariantMonoidal[F]

override def unit[A]: IdT[F, A] = IdT(F0.unit[A])
override def unit: IdT[F, Unit] = IdT(F0.unit)

override def contramap[A, B](fa: IdT[F, A])(f: B => A): IdT[F, B] =
IdT(F0.contramap(fa.value)(f))
Expand Down
10 changes: 3 additions & 7 deletions core/src/main/scala/cats/data/IndexedStateT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -247,10 +247,6 @@ private[data] sealed abstract class IndexedStateTInstances extends IndexedStateT
implicit def catsDataAlternativeForIndexedStateT[F[_], S](implicit FM: Monad[F],
FA: Alternative[F]): Alternative[IndexedStateT[F, S, S, ?]] with Monad[IndexedStateT[F, S, S, ?]] =
new IndexedStateTAlternative[F, S] { implicit def F = FM; implicit def G = FA }

implicit def catsDataContravariantMonoidalForIndexedStateT[F[_], S](implicit FD: ContravariantMonoidal[F],
FA: Applicative[F]): ContravariantMonoidal[IndexedStateT[F, S, S, ?]] =
new IndexedStateTContravariantMonoidal[F, S] { implicit def F = FD; implicit def G = FA }
}

private[data] sealed abstract class IndexedStateTInstances1 extends IndexedStateTInstances2 {
Expand Down Expand Up @@ -387,11 +383,11 @@ private[data] sealed abstract class IndexedStateTContravariantMonoidal[F[_], S]
implicit def F: ContravariantMonoidal[F]
implicit def G: Applicative[F]

override def unit[A]: IndexedStateT[F, S, S, A] =
IndexedStateT.applyF(G.pure((s: S) => F.unit[(S, A)]))
override def unit: IndexedStateT[F, S, S, Unit] =
IndexedStateT.applyF(G.pure((s: S) => F.trivial[(S, Unit)]))
Copy link
Contributor

@kailuowang kailuowang Dec 18, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's reported that this instance is not tested. Shall we add one?

Copy link
Contributor

@kailuowang kailuowang Dec 18, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the ContravariantMonoidal instance of IndexedStateT requires that F to have both FlatMap and ContravriantMonoidal. We can't think of any practical data types that satisfies that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I incline to remove this instance, WDYT @stephen-lazaro ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, it seems at best awkward and unuseful.


override def contramap[A, B](fa: IndexedStateT[F, S, S, A])(f: B => A): IndexedStateT[F, S, S, B] =
contramap2(fa, unit)(((a: A) => (a, a)) compose f)
contramap2(fa, trivial)(((a: A) => (a, a)) compose f)

override def product[A, B](fa: IndexedStateT[F, S, S, A], fb: IndexedStateT[F, S, S, B]): IndexedStateT[F, S, S, (A, B)] =
contramap2(fa, fb)(identity)
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/data/Kleisli.scala
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ private[data] trait KleisliAlternative[F[_], A] extends Alternative[Kleisli[F, A
private[data] sealed trait KleisliContravariantMonoidal[F[_], D] extends ContravariantMonoidal[Kleisli[F, D, ?]] {
implicit def F: ContravariantMonoidal[F]

override def unit[A]: Kleisli[F, D, A] = Kleisli(Function.const(F.unit[A]))
override def unit: Kleisli[F, D, Unit] = Kleisli(Function.const(F.unit))

override def contramap[A, B](fa: Kleisli[F, D, A])(f: B => A): Kleisli[F, D, B] =
Kleisli(d => F.contramap(fa.run(d))(f))
Expand Down
25 changes: 21 additions & 4 deletions core/src/main/scala/cats/data/Nested.scala
Original file line number Diff line number Diff line change
Expand Up @@ -147,27 +147,34 @@ private[data] sealed abstract class NestedInstances8 extends NestedInstances9 {
}

private[data] sealed abstract class NestedInstances9 extends NestedInstances10 {
implicit def catsDataInvariantSemigroupalApplyForNested[F[_]: InvariantSemigroupal, G[_]: Apply]: InvariantSemigroupal[Nested[F, G, ?]] =
new NestedInvariantSemigroupalApply[F, G] {
val FG: InvariantSemigroupal[λ[α => F[G[α]]]] = InvariantSemigroupal[F].composeApply[G]
}
}

private[data] sealed abstract class NestedInstances10 extends NestedInstances11 {
implicit def catsDataFunctorForNested[F[_]: Functor, G[_]: Functor]: Functor[Nested[F, G, ?]] =
new NestedFunctor[F, G] {
val FG: Functor[λ[α => F[G[α]]]] = Functor[F].compose[G]
}
}

private[data] sealed abstract class NestedInstances10 extends NestedInstances11 {
private[data] sealed abstract class NestedInstances11 extends NestedInstances12 {
implicit def catsDataInvariantForNested[F[_]: Invariant, G[_]: Invariant]: Invariant[Nested[F, G, ?]] =
new NestedInvariant[F, G] {
val FG: Invariant[λ[α => F[G[α]]]] = Invariant[F].compose[G]
}
}

private[data] sealed abstract class NestedInstances11 extends NestedInstances12 {
private[data] sealed abstract class NestedInstances12 extends NestedInstances13 {
implicit def catsDataInvariantForCovariantNested[F[_]: Invariant, G[_]: Functor]: Invariant[Nested[F, G, ?]] =
new NestedInvariant[F, G] {
val FG: Invariant[λ[α => F[G[α]]]] = Invariant[F].composeFunctor[G]
}
}

private[data] sealed abstract class NestedInstances12 {
private[data] sealed abstract class NestedInstances13 {
implicit def catsDataInvariantForNestedContravariant[F[_]: Invariant, G[_]: Contravariant]: Invariant[Nested[F, G, ?]] =
new NestedInvariant[F, G] {
val FG: Invariant[λ[α => F[G[α]]]] = Invariant[F].composeContravariant[G]
Expand Down Expand Up @@ -284,11 +291,21 @@ private[data] trait NestedContravariant[F[_], G[_]] extends Contravariant[Nested
private[data] trait NestedContravariantMonoidal[F[_], G[_]] extends ContravariantMonoidal[Nested[F, G, ?]] {
def FG: ContravariantMonoidal[λ[α => F[G[α]]]]

def unit[A]: Nested[F, G, A] = Nested(FG.unit)
def unit: Nested[F, G, Unit] = Nested(FG.unit)

def contramap[A, B](fa: Nested[F, G, A])(f: B => A): Nested[F, G, B] =
Nested(FG.contramap(fa.value)(f))

def product[A, B](fa: Nested[F, G, A], fb: Nested[F, G, B]): Nested[F, G, (A, B)] =
Nested(FG.product(fa.value, fb.value))
}

private[data] trait NestedInvariantSemigroupalApply[F[_], G[_]] extends InvariantSemigroupal[Nested[F, G, ?]] {
def FG: InvariantSemigroupal[λ[α => F[G[α]]]]

def imap[A, B](fa: Nested[F, G, A])(f: A => B)(g: B => A): Nested[F, G, B] =
Nested(FG.imap(fa.value)(f)(g))

def product[A, B](fa: Nested[F, G, A], fb: Nested[F, G, B]): Nested[F, G, (A, B)] =
Nested(FG.product(fa.value, fb.value))
}
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/data/OptionT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ private trait OptionTMonadError[F[_], E] extends MonadError[OptionT[F, ?], E] wi
private trait OptionTContravariantMonoidal[F[_]] extends ContravariantMonoidal[OptionT[F, ?]] {
def F: ContravariantMonoidal[F]

override def unit[A]: OptionT[F, A] = OptionT (F.unit)
override def unit: OptionT[F, Unit] = OptionT(F.trivial)

override def contramap[A, B](fa: OptionT[F, A])(f: B => A): OptionT[F, B] =
OptionT(F.contramap(fa.value)(_ map f))
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/data/Tuple2K.scala
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ private[data] sealed trait Tuple2KContravariant[F[_], G[_]] extends Contravarian
private[data] sealed trait Tuple2KContravariantMonoidal[F[_], G[_]] extends ContravariantMonoidal[λ[α => Tuple2K[F, G, α]]] {
def F: ContravariantMonoidal[F]
def G: ContravariantMonoidal[G]
def unit[A]: Tuple2K[F, G, A] = Tuple2K(F.unit, G.unit)
def unit: Tuple2K[F, G, Unit] = Tuple2K(F.unit, G.unit)
def product[A, B](fa: Tuple2K[F, G, A], fb: Tuple2K[F, G, B]): Tuple2K[F, G, (A, B)] =
Tuple2K(F.product(fa.first, fb.first), G.product(fa.second, fb.second))
def contramap[A, B](fa: Tuple2K[F, G, A])(f: B => A): Tuple2K[F, G, B] =
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/data/WriterT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ private[data] sealed trait WriterTAlternative[F[_], L] extends Alternative[Write
private[data] sealed trait WriterTContravariantMonoidal[F[_], L] extends ContravariantMonoidal[WriterT[F, L, ?]] {
implicit def F0: ContravariantMonoidal[F]

override def unit[A]: WriterT[F, L, A] = WriterT(F0.unit[(L, A)])
override def unit: WriterT[F, L, Unit] = WriterT(F0.trivial[(L, Unit)])

override def contramap[A, B](fa: WriterT[F, L, A])(f: B => A): WriterT[F, L, B] =
WriterT(F0.contramap(fa.run)((d: (L, B)) => (d._1, f(d._2))))
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/instances/eq.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ trait EqInstances {
* Defaults to the trivial equivalence relation
* contracting the type to a point
*/
def unit[A]: Eq[A] = Eq.allEqual
def unit: Eq[Unit] = Eq.allEqual
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not quite sure I understand why this one is reported as not tested either. Any idea?


/** Derive an `Eq` for `B` given an `Eq[A]` and a function `B => A`.
*
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/scala/cats/instances/equiv.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ trait EquivInstances {
* Defaults to trivially contracting the type
* to a point
*/
def unit[A]: Equiv[A] = new Equiv[A] {
def equiv(x: A, y: A): Boolean = true
def unit: Equiv[Unit] = new Equiv[Unit] {
def equiv(x: Unit, y: Unit): Boolean = true
}

/** Derive an `Equiv` for `B` given an `Equiv[A]` and a function `B => A`.
Expand Down
Loading