// NOTE: changed the import from the example
import shapeless.PolyDefns.~>
// choose is a function from Sets to Options with no type specific cases
object choose extends (Set ~> Option) {
def apply[T](s : Set[T]) = s.headOption
}
choose(Set(1, 2, 3))
choose(Set('a', 'b', 'c'))
// NOTE: extending leads to loss of type safety or similar functionality is impossible
// * `object choose1 extends (Set[_] => Option[_]) // type safety gone
// * `object choose1 extends (Set[Any] => Option[Any]) // type safety gone
// * `object choose1[T] extends (Set[T] => Option[T]) // syntax does not exist, objects cannot be parametrized
object choose1 {
def apply[T](s: Set[T]): Option[T] = s.headOption
}
choose1(Set(1, 2, 3))
choose1(Set('a', 'b', 'c'))
// With Shapeless
def pairApply(f: Set ~> Option) = (f(Set(1, 2, 3)), f(Set('a', 'b', 'c')))
pairApply(choose)
// Without Shapeless
// * Set and Option cannot be parametrized on a given type T, because type T must be polymorphic to work on a Set[Int] and Set[Char]
// * The use of Any throws away the type system as a result
// * `choose1.apply` must explicitly be named because `choose1.type` does not match the type of `f`
def pairApply1(f: Set[Any] => Option[Any]) = (f(Set(1, 2, 3)), f(Set('a', 'b', 'c')))
pairApply1(choose1.apply)