Search code examples
arraysscalatypesexistential-type

Understanding parameter types during multidimensional array creation


I'm trying to parse the meaning of the parameter type type _1 >: Char with Int <: AnyVal that is created in the following code (using Scala ammonite repl). I'm defining an array of arrays

  • What is the meaning of with in this context, are we defining a new Char class with the 'traits' of Int?
  • Does the expression >: Char with Int <: AnyVal mean - Any type (_1) that is a supertype of Char with Int but a subtype of AnyVal?
@ val tmix1 = Array(Array[Int](1,2,3), Array[Char]('b','f')) 
tmix1: Array[Array[_1] forSome { type _1 >: Char with Int <: AnyVal }] 
= Array(Array(1, 2, 3), Array('b', 'f'))

Solution

  • Does the expression >: Char with Int <: AnyVal mean - Any type (_1) that is a supertype of Char with Int but a subtype of AnyVal?

    Yes, this is correct.

    are we defining a new Char class with the 'traits' of Int

    We are not defining anything. Are you define a 'class' when you write 'x: Int => String' ? No, it's just type expression. This is a syntax that allows you to express a type. With keyword 'with' you construct a type that is a subtype of Char and subtype of Int. This expression can be used as union type encoding (https://stackoverflow.com/a/6883076/14044371). A union type is a type that combines few types in a single type with logical "Or". It also called "type disjunction". Intuitively you can try to understand this by imagining examples:

    // what is the possible supertypes for type 'Char with Int'?
    // it is 'Char with Int',  Int, Char, AnyVal, Any 
    val x: Char with Int = Char with Int
    val a: Int = Char with Int
    val b: Char = Char with Int
    val c: AnyVal = Char with Int
    val d: An y= Char with Int
    

    so T >: Char with Int and T <: AnyVal almost equivalent to Char Or Int

    For intuition on Char Or Int I can give you this:

    val a: Char Or Int = 1 // is it correct? yes it is
    val b: Char Or Int = 'a' // it is correct too
    // after that, you can pattern match on such type in a safe manner
    def foo(x: Char Or Int) match {
      case Int => ...
      case Char => ...
    }
    

    So.

    You are correct in your second question.

    You are not quite right in the first, because it is not 'class' or 'trait' - it is type expression. This is not intuitive, because you have the same word 'with' like in inheritance of classes and traits. But this word means a little bit different things in different contexts.

    This construction is the way to express union type that suits well as a type for the original expression val tmix1 = Array(Array[Int](1,2,3), Array[Char]('b','f'))