Skip to content

Instantly share code, notes, and snippets.

@hamishdickson
Created May 11, 2017 06:40
Show Gist options
  • Save hamishdickson/a23550ced19283bb5a6d3f2846a3dcd4 to your computer and use it in GitHub Desktop.
Save hamishdickson/a23550ced19283bb5a6d3f2846a3dcd4 to your computer and use it in GitHub Desktop.
package playing
/*
example of f-bounded polymorphism
*/
object Playing {
trait A[T <: Foo[_]] {
type O
def f(t: T): O
}
// note, these have to be declared *before* the ADT otherwise it won't compile
implicit val barA = new A[Bar] {
type O = StringLimit
def f(t: Bar): O = StringLimit(t.s)
}
// note, if you don't have an implementation of A for everything in your ADT then you get a compilation error :)
/*
[info] Compiling 1 Scala source to /Users/hamishdickson/Programming/scala-stuff/holiday-type-playing/target/scala-2.12/classes...
[error] /Users/hamishdickson/Programming/scala-stuff/holiday-type-playing/Playing.scala:22: could not find implicit value for parameter evidence: playing.A[playing.Playing.Baz]
[error] final case class Baz(i: Int) extends Foo[Baz]
[error] ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 0 s, completed 21-Apr-2017 17:08:46
*/
implicit val bazA = new A[Baz] {
type O = IntLimit
def f(t: Baz): O = IntLimit(t.i)
}
// f-bounded polymorphism
// note, a trait won't compile here
sealed abstract class Foo[B <: Foo[B]](implicit val evidence: A[B]) {
def fu(b: B) = implicitly[A[B]].f(b)
}
final case class Bar(s: String) extends Foo[Bar]
final case class Baz(i: Int) extends Foo[Baz]
/*
this no compile (which is what I want - it's not a subtype of Foo)
> compile
[info] Compiling 1 Scala source to /Users/hamishdickson/Programming/scala-stuff/holiday-type-playing/target/scala-2.12/classes...
[error] /Users/hamishdickson/Programming/scala-stuff/holiday-type-playing/Playing.scala:25: type arguments [playing.Playing.Woozle] do not conform to trait A's type parameter bounds [T <: playing.Playing.Foo]
[error] implicit val woozleA = new A[Woozle] {
[error] ^
[error] /Users/hamishdickson/Programming/scala-stuff/holiday-type-playing/Playing.scala:25: type arguments [playing.Playing.Woozle] do not conform to trait A's type parameter bounds [T <: playing.Playing.Foo]
[error] implicit val woozleA = new A[Woozle] {
[error] ^
[error] two errors found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 0 s, completed 20-Apr-2017 12:47:06
case class Woozle(d: Double)
implicit val woozleA = new A[Woozle] {
type O = Double
def f(t: Woozle): O = t.d
}
*/
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment