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.

Tags:

Scala