This question is about _ as used in type constructor and not when used in defining existential types.
So the question is what is the difference when _
is used as type parameter instead of a variable like T
. For example difference between F[_]
and F[T]
.
The only difference I can think of is that with F[_]
the parameter itself can have as many holes as possible...that is F[_]
can become F[Int]
or F[Future[Option[Int]]]
etc...while when you have F[T]
the T
can only be a proper type...that is F[String]
or F[Int]
etc.
Is this a correct assumption? and is that the main difference between F[_]
and F[T]
? or there are more?
What about the case where the two are used as type parameters? For example, what is the difference between trait Functor [F[_]]
and trait Functor [F[T]]
?
Is there any semantic difference if the functor trait is defined as trait Functor [F[_]]
instead of trait Functor [F[T]]
?
The F[_] simply means that F is a type parameter , which is itself a type constructor or a type with a type parameter . As we stated earlier, such a type can be a List , Option , or even a Scala Future .
You can use certain types (like Int or String ) using literals ( 1 or 2 for Int or "James" for String ). Type constructors are types that need other types to be built. List or Option won't be a fully qualified type unless you pass another type to them (i.e. List[Int] or Option[String] – mfirry.
Non-value types capture properties of identifiers that are not values. For example, a type constructor does not directly specify a type of values. However, when a type constructor is applied to the correct type arguments, it yields a first-order type, which may be a value type.
Methods in Scala can be parameterized by type as well as value. The syntax is similar to that of generic classes. Type parameters are enclosed in square brackets, while value parameters are enclosed in parentheses. The method listOfDuplicates takes a type parameter A and value parameters x and length .
To quote the specification:
The above scoping restrictions are generalized to the case of nested type parameter clauses, which declare higher-order type parameters. Higher-order type parameters (the type parameters of a type parameter
t
) are only visible in their immediately surrounding parameter clause (possibly including clauses at a deeper nesting level) and in the bounds of t. Therefore, their names must only be pairwise different from the names of other visible parameters. Since the names of higher-order type parameters are thus often irrelevant, they may be denoted with a_
, which is nowhere visible.Example
Here are some well-formed type parameter clauses:
[S, T] [@specialized T, U] [Ex <: Throwable] [A <: Comparable[B], B <: A] [A, B >: A, C >: A <: B] [M[X], N[X]] [M[_], N[_]] // equivalent to previous clause [M[X <: Bound[X]], Bound[_]] [M[+X] <: Iterable[X]]
So if you have no bounds, as in Functor [F[T]]
, there's no difference at all from Functor [F[_]]
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With