bali182 bali182 - 2 months ago 16
Scala Question

Scala context bounds

Using context bounds in scala you can do stuff like

trait HasBuild[T] {
def build(buildable: T): Something
}

object Builders {
implict object IntBuilder extends HasBuild[Int] {
override def build(i: Int) = ??? // Construct a Something however appropriate
}
}

import Builders._
def foo[T: HasBuild](input: T): Something = implicitly[HasBuild[T]].build(1)
val somethingFormInt = foo(1)


Or simply

val somethingFromInt = implicitly[HasBuild[Int]].build(1)


How could I express the type of a
Seq
of any elements that have an appropriate implicit
HasBuild
object in scope? Is this possible without too much magic and external libraries?

Seq[WhatTypeGoesHere]
- I should be able to find the appropriate
HasBuild
for each element

This obviously doesn't compile:

val buildables: Seq[_: HasBuild] = ???

Answer

Basically I'd like to be able to handle unrelated types in a common way (e.g.: build), without the user wrapping them in some kind of adapter manually - and enforce by the compiler, that the types actually can be handled. Not sure if the purpose is clear.

Something you can do:

case class HasHasBuild[A](value: A)(implicit ev: HasBuild[A])
object HasHasBuild {
  implicit def removeEvidence[A](x: HasHasBuild[A]): A = x.value
  implicit def addEvidence[A: HasBuild](x: A): HasHasBuild[A] = HasHasBuild(x)
}

and now (assuming you add a HasBuild[String] for demonstration):

val buildables: Seq[HasHasBuild[_]] = Seq(1, "a")

compiles, but

val buildables1: Seq[HasHasBuild[_]] = Seq(1, "a", 1.0)

doesn't.