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

Unable to use TransLift as a typeclass #1613

Closed
wedens opened this issue Apr 18, 2017 · 4 comments
Closed

Unable to use TransLift as a typeclass #1613

wedens opened this issue Apr 18, 2017 · 4 comments

Comments

@wedens
Copy link
Contributor

wedens commented Apr 18, 2017

With TransLift I'm unable to use it as a typeclass for liftT function for any transformer.

With MonadTrans I was able to do it. For example to avoid boilerplate in defining typeclass instances for transformers:

def mkTrans[F[_]: Monad, MT[_[_], _]: MonadTrans](implicit F: MyTypeclass[F]): MyTypeclass[MT[F, ?]] = 
  new MyTypeclass[MT[F, ?]] {
    def op = F.op.liftT[MT]
    def op2(a: Int) = F.op2(a).liftT[MT]
  }

implicit def eitherTMyTypeclass[F[_]: Monad: MyTypeclass, E]: MyTypeclass[EitherT[F, E, ?]] = mkTrans[F, EitherT[?[_], E, ?]]

or for liftT as a natural transformation:

def liftTTrans[F[_]: Monad, G[_[_], _]: MonadTrans] =  λ[F ~> G[F, ?]](_.liftT[G])

it can be defined with TransLift as def liftTT[F[_]: Monad, G[_[_], _], H[_[_]]](implicit G: TransLift.Aux[G, H], M: H[F]) = λ[F ~> G[F, ?]](x => G.liftT(x)) but this extra type parameter H makes it useless.

For TransLift to be useful in syntax it uses some scary thing TLExtract. I hope it's not expected to be used in other places where TransLift required as a typeclass.

@djspiewak
Copy link
Member

djspiewak commented Apr 19, 2017

If you're willing to accept a Monad constraint, then you can still implement liftTTrans in more or less the same way that you implemented it with scalaz:

def liftTTrans[F[_]: Monad, G[_[_], _]: TransLift.Aux[?[_[_], _], Monad]] =
  λ[F ~> G[F, ?]](_.liftT[G])

Or at least, you should be able to. At present I don't actually think that will resolve, since it is effectively finding an instance of TransLift which is "too" powerful. At the very least, it wouldn't be difficult to make that work.

You would only need to use TLExtract if you wanted to preserve the full generality of TransLift in your liftTTrans function. That is, the ability to impose a typeclass constraint on F which varies depending on the precise type constructor G.

@wedens
Copy link
Contributor Author

wedens commented Apr 19, 2017

@djspiewak I can accept a Monad constraint.

This liftTTrans definition results in could not find implicit value for parameter extract: cats.syntax.TLExtract[cats.syntax.TLExtract.SingletonMT{type MT[F[_], B] = G[F,B]},cats.syntax.TLExtract.SingletonM{type M[B] = F[B]}]. Also I'm not sure it will work with Kleisli which requires Trivial typeclass or with EitherT which requires Functor.

@djspiewak
Copy link
Member

@wedens We need a bit more implicit machinery to allow stronger constraints to imply weaker ones. I'll give that some thought and see if I can implement it tomorrow. Shouldn't be too hard.

@tpolecat
Copy link
Member

tpolecat commented Apr 21, 2017

I'm stepping aboard this canoe, if you don't mind. Trying to write a LiftTrans equivalent of this and I'm not even sure what its type needs to be, in order to get liftT syntax to work. Refining with { type TC[M[_]] = Monad[M] } doesn't seem to help.

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