## Polymorphic Function Values

#### Polymorphic function values

Ordinary Scala function values are monomorphic. shapeless, however, provides an encoding of polymorphic function values. It supports natural transformations, which are familiar from libraries like Scalaz

`choose` is a function from Seqs to Options with no type specific cases

``````object choose extends (Seq ~> Option) {
}``````
``````choose(Seq(1, 2, 3)) should be(res0)
choose(Seq('a', 'b', 'c')) should be(res1)``````

Being polymorphic, they may be passed as arguments to functions or methods and then applied to values of different types within those functions

``````def pairApply(f: Seq ~> Option) = (f(Seq(1, 2, 3)), f(Seq('a', 'b', 'c')))

pairApply(choose) should be((res0, res1))``````

They are nevertheless interoperable with ordinary monomorphic function values. `choose` is convertible to an ordinary monomorphic function value and can be mapped across an ordinary Scala List

``(List(Seq(1, 3, 5), Seq(2, 4, 6)) map choose) should be(List(res0, res1))``

However, they are more general than natural transformations and are able to capture type-specific cases which, as we'll see below, makes them ideal for generic programming, `size` is a function from Ints or Strings or pairs to a `size` defined by type specific cases

``````object size extends Poly1 {
implicit def caseInt = at[Int](x ⇒ 1)
implicit def caseString = at[String](_.length)
implicit def caseTuple[T, U](implicit st: Case.Aux[T, Int], su: Case.Aux[U, Int]) =
at[(T, U)](t ⇒ size(t._1) + size(t._2))
}

size(23) should be(res0)
size("foo") should be(res1)
size((23, "foo")) should be(res2)
size(((23, "foo"), 13)) should be(res3)``````