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

Transform typeclass #1713

Open
leandrob13 opened this issue May 30, 2017 · 4 comments
Open

Transform typeclass #1713

leandrob13 opened this issue May 30, 2017 · 4 comments

Comments

@leandrob13
Copy link
Contributor

leandrob13 commented May 30, 2017

There has been some discussion about adding a typeclass for dealing with F ~> G transformations in #1644. The original proposal was made by @kailuowang in this gist and I materialized it by the name of Transform. The example below includes only instances for EitherT and Kleisli.

import cats.arrow.FunctionK
import cats.data.{EitherT, Kleisli}
import cats.~>

trait Transform[H[_[_], _]] {
  def map[F[_], G[_], A](ha: H[F, A])(f: F ~> G): H[G, A]

  def lift[F[_], G[_]](f: F ~> G): H[F, ?] ~> H[G, ?] =
    new FunctionK[H[F, ?], H[G, ?]] {
      def apply[A](fa: H[F, A]): H[G, A] = map(fa)(f)
    }
}

object Transform {

  implicit def eitherTTransform[E]: Transform[EitherT[?[_], E, ?]] =
    new Transform[EitherT[?[_], E, ?]] {
      def map[F[_], G[_], A](ha: EitherT[F, E, A])(f: F ~> G): EitherT[G, E, A] =
        EitherT[G, E, A](f(ha.value)) //This should be EitherT's transformF
    }

  implicit def kleisliTransform[E]: Transform[Kleisli[?[_], E, ?]] =
    new Transform[Kleisli[?[_], E, ?]] {
      def map[F[_], G[_], A](ha: Kleisli[F, E, A])(f: F ~> G): Kleisli[G, E, A] =
        ha.transform(f)
    }
}

The pattern is apparent in Kleisli since it already implements transform. For the rest of the monad transformers it is not defined as a F ~> G and it is confusing given that for EitherT and OptionT transform means to bimap/map the inner types. This might be an opportunity to make standard the F ~> G operations in MonadTs and solve the confusion for the actual use of transform.

@edmundnoble
Copy link
Contributor

I can empathize with this requirement, and I would approve a PR that renames the methods to only be transform for higher-kinded mapping. However, cats-mtl has something very close to this in the form of cats.mtl.monad.TransFunctor and cats.mtl.monad.LayerFunctor.

@wedens
Copy link
Contributor

wedens commented May 30, 2017

This typeclass is better known as Hoist or MFunctor.

@leandrob13
Copy link
Contributor Author

@edmundnoble where can I see code for cats.mtl.monad.TransFunctor?

Sure thing about the PR for defining transform accordingly in monad transformers.

@edmundnoble
Copy link
Contributor

This unfortunately is not implementable for StateT. See https://github.com/edmundnoble/cats-mtl/issues/1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants