// Show the reason for the universal array type, Array[*]

proc main()
{
    using oadl::typecheck;

    // Start with three arrays
    var aList = {"one", "two", "three"}; // A List
    var aArr = aList.reshape(2,3); // An Array
    var aPak = [2,3].iterate(); // A PackInt array

    // aList is, in fact, a List
    if (typecheck(List, aList)) { "No error - OK #1\n"; }

    // aList is *not* a multidimensional Array
    try { typecheck(Array, aList); } catch (e) { "", e, " OK #2\n"; }

    // aArr is not a List
    try { typecheck(List, aArr); } catch (e) { "", e, " OK #3\n"; }

    // aArr is a multidimensional Array
    if (typecheck(Array, aArr)) { "No error - OK #4\n"; }

    // aPak *is* a PackInt
    if (typecheck(PackInt, aPak)) { "No error - OK #5\n"; }

    // However, aPak is not a heterogeneous Array
    try { typecheck(Array, aPak); } catch (e) { "", e, " OK #6\n"; }

    // There is, therefore, a type difference, between a heterogeneous
    // multidimensional Array and a heterogeneous single-dimensional
    // List. There is also a type deference between a heterogeneous
    // multidimensional Array and a homogeneous multi-dimensionsal
    // packed PackInt array. The universal array type, Array[*],
    // encompasses all of these types, as shown below.

    // aPak is also a generic, universal Array
    if (typecheck(Array[*], aPak)) { "No error - OK #7\n"; }

    // So is aList
    if (typecheck(Array[*], aList)) { "No error - OK #8\n"; }

    // And so is aArr
    if (typecheck(Array[*], aArr)) { "No error - OK #9\n"; }
}