J Pullar
J Pullar

Reputation: 1935

Scala Unable to pimp NaturalTransformation in scalaz or cats

For some reason the following fails to work

object NtExtTest {
  implicit class NaturalTransformExt[M[_], N[_]](val self: NaturalTransformation[M,N]) extends AnyVal {
    def test(b:Boolean) = b
  }
 }

when I call the method test on a natural transform. Intellij recognises it as an extension function, but the compile gives value test is not a member of cats.~> . The same happens when using the scalaz NaturalTransformation. Is there something I can do to help the compile recognise the extension?

Scala version is 2.11.8

An example which fails:

  import NtExtTest._

  class NtTest[B] extends NaturalTransformation[Either[B,?], Xor[B,?]] {
    def apply[A](fa: Either[B, A]): Xor[B, A] = {
      fa match {
        case Left(l) => Xor.left(l)
        case Right(r) => Xor.right(r)
      }
    }
  }

  val test = new NtTest[String]
  test.test(false)

(above uses kind projector plugin, but equally fails with type lambdas, or single param higher kinded types)

Upvotes: 0

Views: 86

Answers (1)

muradm
muradm

Reputation: 2053

Probably relates to SI-8286

object NtExtTest {
  // this will work
  implicit class NatTransExt1[E](val t: NaturalTransformation[Either[E, ?], \/[E, ?]]) {
    def test1(b: Boolean): Boolean = false
  }

  // and this will work
  implicit class NatTransExt2[E](val t: NtTest[E]) {
    def test2(b: Boolean): Boolean = false
  }

  // but this will not work, because NaturalTransformation[F, G] and
  // NaturalTransformation[Either[E, ?], \/[E, ?]] of different kind
  implicit class NatTransExt3[F[_], G[_]](val s: NaturalTransformation[F, G]) {
    def test3(b: Boolean): Boolean = false
  }
}

I.e. it is not related to NaturalTransformation. It does not work in simple case as well:

trait SomeType[F[_]]

class SomeConcreteType[A] extends SomeType[Either[A, ?]]

object SomeTypeExt {
  // this will not compile
  implicit class SomeTypeEnrich[F[_]](val t: SomeType[F]) {
    def test1: Boolean = false
  }
  // this will
  implicit class SomeConcreteEnrich[A](val t: SomeType[Either[A, ?]]) {
    def test2: Boolean = true
  }
}

If the goal to extend NtTest, probably NatTransExt1 would be best choice if one would like to stay as generic as possible. NatTransExt2 is ok, if extension really specific to NtTest.

Upvotes: 0

Related Questions