summaryrefslogtreecommitdiff
path: root/test/files/neg/t3346c.scala
blob: a5ac166b2d4f70301772b80c18f37977e088b2bc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
object Test extends App {
  //
  // An attempt to workaround SI-2712, foiled by SI-3346
  //
  trait TC[M[_]]

  type EitherInt[A] = Either[Int, A]

  implicit object EitherTC extends TC[EitherInt]

  def foo[M[_]: TC, A](ma: M[A]) = ()

  val eii: Either[Int, String] = Right("")

  foo[EitherInt, String](eii)

  // This one needs SI-2712 Higher Order Unification
  //foo(eii) // not inferred

  // A workaround is to provide a set of implicit conversions that take values
  // based on type constructors of various shapes, and search for the
  // type class instances.
  //
  // This is the approach taken by scalaz7.

  trait TCValue[M[_], A] {
    implicit def self: M[A]
    def M: TC[M]

    // instead of `foo(eii)`, we'll try `eii.foo`
    def foo[M[_], A] = ()
  }


  implicit def ToTCValue[M[_], A](ma: M[A])(implicit M0: TC[M]) = new TCValue[M, A] {
    implicit val M = M0
    val self = ma
  }
  implicit def ToTCValueBin1[M[_, _], A, B](ma: M[A, B])(implicit M0: TC[({type λ[α]=M[A, α]})]): TCValue[({type λ[α] = M[A, α]}), B] = new TCValue[({type λ[α]=M[A, α]}), B] {
    implicit val M = M0
    val self = ma
  }
  implicit def ToTCValueBin2[M[_, _], A, B](ma: M[A, B])(implicit M0: TC[({type λ[α]=M[α, B]})]): TCValue[({type λ[α]=M[α, B]}), A] = new TCValue[({type λ[α]=M[α, B]}), A] {
    implicit val M = M0
    val self = ma
  }


  ToTCValueBin1(eii).foo

  // as expected, could not find implicit parameter
  // ToTCValueBin2(eii).bar

  // error: implicit conversions are not applicable because they are ambiguous, both method ToTCValueBin1 ... and  method ToTCValueBin2
  //        annoying!!
  //        https://issues.scala-lang.org/browse/SI-3346
  //
  // Works if we remove ToTCValueBin2
  //
  eii.bar
}