|
| 1 | +import scala.math.Ordering |
| 2 | +import scala.reflect.ClassTag |
| 3 | + |
| 4 | +trait Sam { def apply(x: Int): String } |
| 5 | +trait SamP[U] { def apply(x: Int): U } |
| 6 | + |
| 7 | +class OverloadedFun[T](x: T) { |
| 8 | + // def foo(f: T => String): String = f(x) Can't unify - need just type equality |
| 9 | + def foo(f: Any => String): String = f(x) |
| 10 | + def foo(f: Any => T): T = f("a") |
| 11 | + |
| 12 | + def poly[U](f: Int => String): String = f(1) |
| 13 | + def poly[U](f: Int => U): U = f(1) |
| 14 | + |
| 15 | +// def polySam[U](f: Sam): String = f(1) Only function types supported for pretype-args |
| 16 | +// def polySam[U](f: SamP[U]): U = f(1) |
| 17 | + |
| 18 | + // check that we properly instantiate java.util.function.Function's type param to String |
| 19 | + def polyJavaSam(f: String => String) = 1 |
| 20 | + def polyJavaSam(f: java.util.function.Function[String, String]) = 2 |
| 21 | +} |
| 22 | + |
| 23 | +class StringLike(xs: String) { |
| 24 | + def map[A](f: Char => A): Array[A] = ??? |
| 25 | + def map(f: Char => Char): String = ??? |
| 26 | +} |
| 27 | + |
| 28 | +object Test { |
| 29 | + val of = new OverloadedFun[Int](1) |
| 30 | + |
| 31 | + of.foo(_.toString) |
| 32 | + |
| 33 | + of.poly(x => x / 2 ) |
| 34 | + //of.polySam(x => x / 2 ) |
| 35 | + of.polyJavaSam(x => x) |
| 36 | + |
| 37 | + val sl = new StringLike("a") |
| 38 | + sl.map(_ == 'a') // : Array[Boolean] |
| 39 | + sl.map(x => 'a') // : String |
| 40 | +} |
| 41 | + |
| 42 | +object sorting { |
| 43 | + def stableSort[K: ClassTag](a: Seq[K], f: (K, K) => Boolean): Array[K] = ??? |
| 44 | + def stableSort[L: ClassTag](a: Array[L], f: (L, L) => Boolean): Unit = ??? |
| 45 | + |
| 46 | + stableSort(??? : Seq[Boolean], (x: Boolean, y: Boolean) => x && !y) |
| 47 | +} |
| 48 | + |
| 49 | +// trait Bijection[A, B] extends (A => B) { |
| 50 | +// def andThen[C](g: Bijection[B, C]): Bijection[A, C] = ??? |
| 51 | +// def compose[T](g: Bijection[T, A]) = g andThen this |
| 52 | +// } |
| 53 | + |
| 54 | +object SI10194 { |
| 55 | + trait X[A] { |
| 56 | + def map[B](f: A => B): Unit |
| 57 | + } |
| 58 | + |
| 59 | + trait Y[A] extends X[A] { |
| 60 | + def map[B](f: A => B)(implicit ordering: Ordering[B]): Unit |
| 61 | + } |
| 62 | + |
| 63 | + trait Z[A] extends Y[A] |
| 64 | + |
| 65 | + (null: Y[Int]).map(x => x.toString) // compiled |
| 66 | + (null: Z[Int]).map(x => x.toString) // didn't compile |
| 67 | +} |
| 68 | + |
| 69 | +// Perform eta-expansion of methods passed as functions to overloaded functions |
| 70 | +trait A { def map[T](f: Int => T): Unit = () } |
| 71 | +object B extends A { |
| 72 | + def noover(f: SAM[Int, Any]): Unit = () |
| 73 | + def map[T: scala.reflect.ClassTag](f: Int => T): Unit = () |
| 74 | + def f(x: Int) = x |
| 75 | + noover(f) |
| 76 | + noover(identity) |
| 77 | + map(f) // same param type, monomorphic method |
| 78 | + map(identity) // same param type, polymorphic method |
| 79 | + |
| 80 | + // must not lub to an incompatible function type |
| 81 | + object t { def f(x: Int => Int): Int = 0; def f(y: String => Int): String = "1" } |
| 82 | + def fun(x: Int) = x |
| 83 | + def fun2[T] = (x: T) => 42 |
| 84 | + t.f(fun) // different param type, monomorphic method |
| 85 | + //t.f(fun2) // different param type, polymorphic method - not possible |
| 86 | +} |
| 87 | + |
| 88 | +// The same for SAM types |
| 89 | +trait SAM[-T, +R] { def apply(x: T): R } |
| 90 | +trait A2 { def map[T](f: SAM[Int, T]): Unit = () } |
| 91 | +object B2 extends A2 { |
| 92 | + def noover(f: SAM[Int, Any]): Unit = () |
| 93 | + def map[T: scala.reflect.ClassTag](f: SAM[Int, T]): Unit = () |
| 94 | + def f(x: Int) = x |
| 95 | + noover(f) |
| 96 | + noover(identity) |
| 97 | + map(f) // same param type, monomorphic method |
| 98 | + //map(identity) // same param type, polymorphic method - not possible for SAMs |
| 99 | + |
| 100 | + // must not lub to an incompatible function type |
| 101 | + object t { def f(x: SAM[Int, Int]): Int = 0; def f(y: SAM[String, Int]): String = "1" } |
| 102 | + def fun(x: Int) = x |
| 103 | + def fun2[T] = (x: T) => 42 |
| 104 | + t.f(fun) // different param type, monomorphic method |
| 105 | + //t.f(fun2) // different param type, polymorphic method - not possible |
| 106 | +} |
0 commit comments