What is type and what is type constructor in scala
In type-level programming you’d think of a List[+A] being a type constructor:
That is:
-List[+A] takes a type parameter (A),
-by itself it’s not a valid type, you need to fill in the A somehow - "construct the type",
-by filling it in with String you’d get List[String] which is a concrete type.
In Scala it is not valid to say something is of type List. Scala is more strict here, and won’t allow us to use just a List in the place of a type, as it’s expecting a real type - not a type constructor.
In brief: List[+A] is a type constructor whereas List[String] is a real type.
In a scala val
assignment like the above:
val name: Tpe = expression
Tpe
is the type of the identifier name
. Hence:
val x: List.type = List
The type of the List
object (aka List module or List companion) is List.type
. This indicates that it is a singleton. All of this is completely orthogonal to the concept of a type constructor in type theory.
Type Constructors
In type theory, List
(note: not the companion) is both a type (denoted *
) and a type constructor (denoted * -> *
) because when you supply a type argument to List
(e.g. Int) then you have a type (i.e. List[Int]
). Scala provides syntax for this construction. For example:
def foo[F[_]]: F[Int]
^^^^ ^^^
| + supply a type argument to F[_]
|
+ the type constructor F[_]
But you cannot really implement such a method unless you know more about F
. For example, if there is a implicit scalaz.Monad[F]
, you might use the Monad.pure
value to construct your F[Int]
like so:
def foo[F[_]: Monad]: F[Int] = Monad[F].pure(1)
In Scala
Scala does let you pass around List
as a type constructor as a type parameter to such a method. For example:
scala> def foo[F[_]]: F[Int] = ???
foo: [F[_]]=> F[Int]
scala> lazy val x = foo[List]
x: List[Int] = <lazy>
However the List
you are supplying in foo[List]
is not the companion
Note the declaration of foo
will result in the following warning:
<console>:11: warning: higher-kinded type should be enabled
by making the implicit value scala.language.higherKinds visible.
This can be achieved by adding the import clause 'import
scala.language.higherKinds'
or by setting the compiler option -language:higherKinds.
See the Scaladoc for value scala.language.higherKinds for a discussion
why the feature should be explicitly enabled.
def foo[F[_]]: F[Int] = ???
^
what keyword type means when I write the following
type
is a member defined on object
in Scala.
Suppose you have a class and its companion object:
class Foo(a: String)
object Foo {
def apply(a: String) = new Foo(a)
}
Now suppose you want to write a method that accepts the object Foo
as an input. What's its type?
If you write this:
def someMethod(fooObj: Foo) = fooObj.apply("x") // doesn't compile
it's not going to compile. Foo
refers to the type of an instance of the class (i.e. the one returned by new Foo("x")
or Foo("x")
). That's why objects have a type
member that can refer to their own type:
def someMethod(fooObj: Foo.type) = fooObj.apply("x") // compiles!
In your specific example List.type
is the type of the companion object of List
. Here's a couple of examples that I hope will clarify what it means:
val listObj: List.type = List
val anEmptyList: List[Int] = listObj.empty[Int] // List()
val aListOfIntegers: List[Int] = listObj.range(1, 4) // List[(1, 2, 3)
And how this type related to type that can be defined as a field in a trait for example.
The type
keyword defines a type member. .type
is a type member. Conceptually it's like every object in Scala has a type member named type, like this:
object Foo {
type type = Foo
}
Obviously this won't compile, but it gives you an idea of what it may look like.