0

I am doing a basic exercise to understand scala user defined types. Consider the following example:

type MyType[T <: AnyVal] = (List[Seq[T]], String, String)
val g: MyType = (List(Seq(1, 2), Seq(3, 4), (Seq(5, 6))), "foo", "bar")

This fails to compile, with type error:

type MyType takes type parameters
[error]     val g: MyType = (List(Seq(1, 2), Seq(3, 4), (Seq(5, 6))), "foo", "bar")

However, this compiles:

type MyType[T <: AnyVal] = (List[Seq[T]], String, String)
val g: MyType[Int] = (List(Seq(1, 2), Seq(3, 4), (Seq(5, 6))), "foo", "bar")

Is there a way so that Scala can automatically determine the type without needing to specify the exact paramter type? I know for functions we can do the following:

import scala.reflect.ClassTag

def f1[T](lst: List[T])(implicit ev: ClassTag[T]) = {
  lst.toArray
}

In which case I do not need to call f1Int explicitly, I can just do f1(...) and it works.

Mario Galic
  • 47,285
  • 6
  • 56
  • 98
finite_diffidence
  • 893
  • 2
  • 11
  • 20
  • Maybe this can answer you https://stackoverflow.com/questions/21147001/why-scala-doesnt-infer-type-from-generic-type-parameters? – Johnny Jun 12 '20 at 13:13
  • 1
    Your example with functions doesn't have anything to with your problem. Scala can infer types, but if you are explicit you have to be explicit about everything. – Luis Miguel Mejía Suárez Jun 12 '20 at 13:29

1 Answers1

3

You can just write

val g = (List(Seq(1, 2), Seq(3, 4), (Seq(5, 6))), "foo", "bar")

and compiler will infer the type. You can check that g: MyType[Int] compiles.

Also you can do

def TypeOf[F[_ <: AnyVal]] = new PartiallyAppllied[F]
class PartiallyAppllied[F[_ <: AnyVal]] {
  def apply[A <: AnyVal](fa: F[A]) = fa
}

val g = TypeOf[MyType]((List(Seq(1, 2), Seq(3, 4), (Seq(5, 6))), "foo", "bar"))

g: MyType[Int]
Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
  • 1
    Exactly. Scala *can* infer the type. But if you want to write it down yourself, you have to write the complete type, not just part of it. – Thilo Jun 12 '20 at 13:20
  • 1
    As for the "counter-example", you cannot declare a function like `def f1[T](lst: List[T])(implicit ev: ClassTag)` either. Both `List` and `ClassTag` need to get their full signature. You can put `List[_]` but not just `List`. – Thilo Jun 12 '20 at 13:25