Reputation: 8462
I'm talking about this (and only about parametric polymorphism):
def fun1[T](s: Set[T]): Option[T] = s.headOpton
I've seen in a few places when people call this an example of polymorphic function around T
in raw scala - something like in shapeless Set ~> Option
.
But I do not understand why we can call it polymorphic. Even though we seem to be able to pass there both Set[Int]
and Set[String]
in reality fun1[Int]
and fun1[String]
are two different functions. I think I can claim that because eta-expansion of fun1
is wrong and does not give us what we want:
scala> fun1 _
res0: Set[Nothing] => Option[Nothing] = <function1>
And we need to always mention a type when we expand:
scala> fun1[Int]_
res1: Set[Int] => Option[Int] = <function1>
I am trying to study shapeless and I try to compare it with the raw scala - that's where the question is coming from. Do I understand it correctly?
Upvotes: 4
Views: 200
Reputation: 8103
fun1
implementation is not dependent on the type T
therefore it is written generically:
Using parametric polymorphism, a function or a data type can be written generically so that it can handle values identically without depending on their type.
(source Wikipedia)
I agree when you mention that fun1[Int]
and fun1[String]
"are two different functions". These are adopting a "concrete type":
Parametric polymorphism refers to when the type of a value contains one or more (unconstrained) type variables, so that the value may adopt any type that results from substituting those variables with concrete types.
(source Haskell wiki)
EDIT after @Travis and @Miles comments:
As Travis clearly explained, we can have polymorphic methods in "plain scala" but not polymorphic functions. In this article Miles implements using Poly
exactly the polymorphic function mentioned in this question:
object headOption extends PolyFunction1[Set, Option] {
def apply[T](l: Set[T]): Option[T] = l.headOption
}
scala> headOption(Set(1, 2, 3))
res2: Option[Int] = Some(1)
Upvotes: 2