Package tofu.syntax provides helpful syntax extensions, that cats-core lacks. This is suggestion to add few more extension methods.
The problem is that default cats-core extension methods .void and .as from Functor are error-prone.
For example, we have the following piece of code:
def get[F[_]]: F[String] = ???
def consume(s: String): String = ???
def getAndConsume[F[_]: Applicative]: F[Unit] =
get.map(consume).void
At some point of time, we need to make consume method effectfull.
So, we replace it to something like:
def consume[F[_]: Applicative](s: String): F[String] = ???
The problem is that getAndConsume still compiles, it's easy to forget to fix it.
The idea is to add methods .void_/.as_ to tofu.syntax that check this.
The implementation could be something like:
// evidence that A <: F[B]
trait SubtypeOfSome[A, F[_]]:
type B
object SubtypeOfSome:
type Aux[A, F[_], _B] = SubtypeOfSome[A, F] { type B = _B }
given [F[_], _B, A <: F[_B]]: SubtypeOfSome.Aux[A, F, _B] =
new SubtypeOfSome[A, F]:
type B = _B
extension [F[_], A](fa: F[A])
def void_(using Functor[F], NotGiven[SubtypeOfSome[A, F]]): F[Unit] =
Functor[F].void(fa)
def as_[B](b: B)(using Functor[F], NotGiven[SubtypeOfSome[A, F]]): F[Unit] =
Functor[F].as(fa, b)
This solution doesn't help in cases like ReaderT[IO, Ctx, IO[???]], but works in most cases.
Package
tofu.syntaxprovides helpful syntax extensions, that cats-core lacks. This is suggestion to add few more extension methods.The problem is that default cats-core extension methods
.voidand.asfromFunctorare error-prone.For example, we have the following piece of code:
At some point of time, we need to make
consumemethod effectfull.So, we replace it to something like:
The problem is that
getAndConsumestill compiles, it's easy to forget to fix it.The idea is to add methods
.void_/.as_totofu.syntaxthat check this.The implementation could be something like:
This solution doesn't help in cases like
ReaderT[IO, Ctx, IO[???]], but works in most cases.