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
}
|