Introduction

Every decade a new big mainstream language is born. 2010 has passed and we are overdue.

Copute is designed to be the best language for wide scale cooperation, i.e. random contribution and composition. Copute is also designed to naturally express concurrent semantics, for automated parallelization scaling without the aliasing errors of other fundamentally flawed (i.e. shoehorned) approaches.

Copute is based on essentially the same grammar as JavaScript, and it adds powerful static typing and pure function options. Copute supports mixing dynamic typing, static typing, pure functions, and impure functions in same program.

The Copute language is composed of five fundamentals, type, instance reference, expression, function, and imperative scope.

A Copute source code file is implicitly wrapped in an anonymous function that is called at initialization.

Purity

Functional programming is fundamentally directed at function level granularity of composability and evaluation order, given by the mathematical properties (associativity, etc) of the Lambda calculus. A pure (a/k/a referentially transparent) function has no side-effects and its return value is determined solely by its input, and not dependent on the spaghetti state of mutable data and external I/O. Pure functions are thus composable in any scenario defined by their inputs, and their evaluation order indeterminism allows the compiler to automatically optimize for lazy evaluation and/or massively parallel threading (which will be important for at least latency and maximum CPU resource utilization as we move to 100+ CPU cores in next several years due to Moore's law) without any possibility for deadlocks nor overhead on the programmer to declare semaphores, mutexes, or other parallelism management (all of which are not scalable).

Since a pure function always returns the same value for same input argument(s), then f( 3, g() ) may be evaluated in any of the following orders.

f( 3 )( g() )        // curry f on argument 3, then call curried function on argument g()'s return value
f( 3 )( \-> g() )    // delay call of g() until its return value is used, i.e. lazy evaluation
f( _, g() )( 3 )     // curry f on argument g()'s return value, then call curried function on argument 3
f( _, \-> g() )( 3 ) // curry f on lazy call to get g()'s return value, then call curried function on argument 3

Copute exceeds the the purity flexibility of Haskell, in that each function can optionally retain compositionally purity (single-threaded function call order-independence, i.e. associativity) while forsaking multi-threading. Thus enabling granular composition of the advantages of pre-existing pure functional programming with the advantages of a traditional OOP language, in a syntax familiar and natural to the masses of imperative programmers, along with the ability to intermix type inference, explicitly typed, run-time (un)typed, every-statement-is-an-expression, and impure code in novel ways. Copute strives for minimum verbosity without sacrificing too much the wealth of familiarity with the "C-like" syntax similarities of C, C++, C#, Java, PHP, and JavaScript genre. In short, pure functional programming for the masses.

Exceptions

Catching exceptions is a language design error that is not repeated in Copute. Catching an exception puts the program in a random state, because it is bypasses deterministic static typing of invariants. By definition of determinism, in every case where the is a determinstic state to bubble an exceptional condition to, i.e. to deterministically recover from an exceptional condition, this bubbling can be accomplished statically at compile-time. It is another way of saying that halting the program when it is in an non-deterministic state, is "given more eyeballs, all bugs are shallow".

Catching exceptions is bubbling of program bugs at run-time. Some dynamically typed languages bubble deterministically instead of longjump.

Copute's compile-time (a/k/a static) typing of a function's type (i.e. the invariants of a function's interface) deterministically bubbles certain types of program bugs at compile-time. The key advantage of static typing, over dynamic typing, is that bugs can bubble at compile-time. Thus Copute has no . Copute does have (i.e. halt) because the type of bugs that apply to exceptions, bubble (at compile-time) as far as the programmer's type design provides. Thus any bugs that cause failed assertions in the programmer's type design, have no coherence with the type design's semantics and mean the program is in a random state (that thus must be halted).

The type of bugs that deterministically bubble coherently at compile-time, are those that are not semantic logic errors in the programmer's type design. Semantic logic errors means the program is by design in an incoherent, random state (that thus must be halted). Thus semantic logic errors that randomly trip on an exception, should be handled the same as bugs which deterministically bubble at compile-time and trip on an exception. Halting the program may be restarting the program from (i.e. rewinding to) a historic copy of coherent state, and/or reporting into a debugger.

There was a long fruitful discussion that illuminated the above concepts. Consider the following example, which asserts the invariants of the function (f) at compile-time, i.e. the function's invariants are statically typed and the (i.e. halt) is provably bubbled outside of the function at compile-time.

class NonZeroDiff
{
   a, b // also these might be declared to be read only outside the new() constructor
   new( a : Int, b : Int )
   {
      if (a – b == 0) throw "Unexpected inputs"
      this.a = a
      this.b = b
   }
}

function f( ab : NonZeroDiff )
{
   return (ab.a * ab.b) / (ab.a – ab.b)
}

result = f( new NonZeroDiff( 2, 1 ) )

Compare the above, to the following example, which asserts the invariants of the function (f) at run-time, i.e. the function's invariant type is dynamically typed. The inputs to the function (f) are statically typed Int, but the invariants a - b != 0 is not asserted by Int inputs, and instead the (i.e. halt) is inside the function at compile-time and can only bubble at run-time.

function f( a : Int, b : Int )
{
   // could instead be thrown by the / operator
   if (a – b == 0) throw "Unexpected inputs"
   return (a * b) / (a – b)
}

result = f( 2, 1 )

The fundamental conclusion is that in dynamic typing, the check is inside the function (f) being reused, and in static typing the check is outside the function, in the type of the invariants specified by the function’s type. Thus in the dynamic-typing case, the function inherently bind's its internal check in a futures contract to the universe of possible external code (because the external code is not forced by the compiler, to do a check itself), i.e. tries to in vain to define the limit of the external universe. Whereas, in the static-typing case, the external code is forced to check for itself, in order to comply with the compile-time checked invariants of the function. That external code has the option of passing this invariants check to (a member of) its containing function's type, thus bubbling the check up the function call hierarchy. If that external code does not bubble the invariant to its containing function's type at compile-time, then any run-time error of supplying incorrect arguments to the constructor of NonZeroDiff will . But at least the external code has the option of bubbling the check further at compile time, unlike the case of within function (f) where the external code has not option to bubble at compile-time and the run-time bubbling is a disorderly (a/k/a random state) composition, because the function (f) can't know all permutations of external code a priori. And that really is the key insight. Compile-time bubbling, versus run-time bubbling, because is orthogonal to any compile-time checking on function type.

Convert Exceptions to Types

Post-conditions can always be converted to a IMaybe return type, which thus forces the caller to do a conditional test to unbox the return value.

Pre-conditions can sometimes be restructured semantically to post-conditions. For example, a fold on a collection that does not input a starting accumulator, could either demand a pre-condition of a non-empty collection, or return a post-condition of IMaybe<Collection>.

Some cases of pre-conditions do not work semantically as post-conditions. For example, construction of (cast to) an unsigned integer type. Declaring all unsigned integers to be IMaybe<Int>, would complicate logic downstream, e.g. IMaybe<Int>.none returned for the length of a collection has caused the program to miss a conditional test upstream. Pre-conditions can always be pushed to post-conditions upstream, by creating a new type with a post-condition. For example, construction of an unsigned integer could take an input of type Unsigned<Int>, which is class with a private constructor (which ony ISignedState<Int> has access to) that inherits from ISignedState<Int>. In order to construct a type Unsigned<Int>, one must construct a ISignedState<Int>, and then do IsInstanceOf conditional test in order to obtain the Unsigned type to pass to the constructor of an unsigned integer. The implementation is elegant.

Perhaps the only justification for using exceptions instead of typing to force post-conditional unboxing tests, is performance applications.

In Copute, Typestate-like compile-time checking can be done by converting assertions to types. For example, to assert that a file is open before closing it, then File.open() could return an OpenFile type, which contains a close() method that is not available in File. Typestate declares and enforces state invariants orthogonal to type, which may have benefits and drawbacks. Typestate could be added to Copute if we encounter compelling benefits.

Java®

Java can emulate some of Copute's features, but with boilerplate that makes coding inefficient, verbose, and obfuscates semantics.

Copute has Java equivalent
Optional typing Employ reflection with every type in entire program inherited from the type, and dynamic<T> emulated with Hashtable<String, T>.
Functional programming
Higher-order Function
Employ anonymous class library.
Closure Employ anonymous class instance, and the otherwise final referenced external variable(s), must be wrapped in a class so the variable(s) can be modified in the closure (because the final is transferred to the wrapping class instance reference).
Anonymous function none. Thus can't embed domain-specific language, see Scala.
Type inference none
Optional parameter
with default
Overload arity, but to skip optional parameters can cause permutated proliferation of overloads, and juxtaposed optional parameters of the same type can not be skipped via overloading. Thus in those cases, Copute's single underscore wildcard _ must be instead a manual application of the default argument value, which thus violates the single-point-of-truth of declaring default values at one place in the formal parameter declaration.
Currying Employ anonymous class library. I have not yet researched to what degree a Java library would have the same issues I have enumerated for Scala on this comparison to Copute's currying.
Pure function none. Implements a pure function, but the pureness invariants are not checked by the compiler.
Mixin multiple inheritance. none
Properties none. Employ boilerplate, which defeats the point, since properties merely exist to reduce boilerplate.
Typed ordered sequence
(a/k/a tuple)
Employ a class for each class Tuple<A, B, ...> { ... }.
Destructuring sequence
return to local instances
none. (a/k/a Java lacks destructured multiple value return from method)
Range-of-integers
(i.e. ordinals)
none. Each range-of-integers type as a class, but the arguments of the construction of an instance is not checked at compile-time so the constructor can throw an exception.
constructor as
orthogonal subclass
Java enum cases share same member data (see Planet example). Instead of enum, expand boilerplate to Copute's documented class hierarchy equivalent.
constructor
pattern match destructuring
Expand boilerplate to equivalent conditional test and class member dereferencing.
parametric inheritance. none. Java has no immutable semantics, thus inefficient copying of subclass parametric members to an instance of the superclass parametric type.
No runtime exception for
static typed collection
none. This compiles, but Java throws runtime exception, String[] strings = {"foo"}; Object[] objects = strings; objects[0] = new Object();
Runtime parametric
type-safety
none. Java does erasure of parametric type. Type-safety is can't be preserved in numerous scenarios, including runtime linkage such as a FFI.
No of exception none. Java has the harmful feature.
Fully implemented class only. none. Java allows partial implementation of an abstract class, which is harmful.
No method Java has the harmful feature, but Copute does too via , but at least discouraged.
No finalizers none. Java has the harmful feature.
operator overloading none. Copute does not overload ==, !=, &&, and || (but does === and !==). The debate and implementation ideas are still being contemplated.
expression This is only a proposed Copute feature, so Java equivalent has not yet been researched.
Constructor in an . none
property with write access , or a pass-by-value immu instance. final. Copute's property semantics are more intuitive and unified, because some programmers don't grasp that final does not mean the pass-by-reference instance is immutable. And is more meaningful for instances that are not class members, which has no analog in Java.

Scala

Scala has some of the features of Copute, except no pure functions, and Scala's syntax is not entirely C-like, so it may not be as naturally familiar to as many programmers as Copute's syntax. Scala has some features that Copute does not have, but these are considered to add complexity for no fundamental gain in expressive power relative to the "Expression Problem" for extension. Copute is designed to output to the source code of multiple languages, such as Java and JavaScript. Scala has some critical design flaws (the first several listed below), which make abstraction impossible, and violate single-point-of-truth.

Copute has Scala equivalent
Pure function none. Implements a pure function, but the pureness invariants are not checked by the compiler.
Interface. none. Trait, but allows harmful conflation of mixin implementation with the abstract type. Referencable implementation Should Be Private, which Scala can't enforce, because the trait is interface and mixin implementation combined, i.e. a trait is a referencable type.
Mixin. none. Trait, but allows harmful conflation of mixin implementation with the abstract type. Referencable implementation Should Be Private, which Scala can't enforce, because the trait is interface and mixin implementation combined, i.e. a trait is a referencable type and a trait may have implementation.
Static, even within an . none. Scala has singleton objects and potentially harmful implicits, but these do not provide the low verbosity, simplicity, single-point-of-truth, and inheritance structure.
Useful anonymous structural type, without harmful forms of static duck typing. Slow and useful anonymous structural type, with erroneous inference of semantics.
Optional parameter
with default and skipping
Correction: this is supported as of version 2.8. none. Overload arity, but to skip optional parameters can cause permutated proliferation of overloads, and juxtaposed optional parameters of the same type can not be skipped via overloading. Thus in those cases, Copute's single underscore wildcard _ must be instead a manual application of the default argument value, which thus violates the single-point-of-truth of declaring default values at one place in the formal parameter declaration.
No of exception none. Scala has the harmful feature.
and none. See section 7.6 "Living without break and continue" in Programming in Scala (Odersky, Spoon, Venners). Convert to an extra boolean test in the expression. Convert each conditional test containing into an if-else. Scala claims these keywords conflict with function literals, but Copute simply limits their scope to the function in which they appear, thus and are not allowed in a function literal, unless the keywords are contained within a loop within a function.
property with write access , or a pass-by-value immu instance. val conflates reference declaration and access control, and has nothing to do with mutability. Copute's property semantics are more intuitive and unified, because some programmers don't grasp that val does not mean the pass-by-reference instance is immutable. And , which has no analog in Scala, is more meaningful for instances that are function parameters or local variables and not class members.
Optional typing Safely downcast to Any then later upcast back an expected type. Scala employs reflection behind the scenes. There will be a Dynamic type in Scala 2.9.
Currying Each of Copute's single underscore wildcard _ arguments must be discarded, except where the possible overloads require an occurrence be replaced with a manual application of the default argument value. Copute's double underscore wildcard __ arguments must be changed to Scala's single underscore wildcard.
Pass-By-Expression It is call-by-name in Scala, which helps for type-checked embedding of a domain-specific language, which can be done by any as follows in Copute.
whileLoop( i > 0,
   {
      println(i)
      i -= 1
   }
)
whileLoop (i > 0)
   ({
      println(i)
      i -= 1
   })
whileLoop (i > 0)
   ((
      println(i),
      i -= 1
   ))

Copute doesn't allow dropping of the parenthesis around each function argument, because Scala code is unreadable because of it.

Although Copute does allow overloading most of the builtin operators, Copute doesn't allow any method name to be an operator -- a feature which decreases verbosity in Scala embedding, but also can cause code to be semantically unclear to someone not familiar with that domain-specific syntax.

An editor program's optional display transformation could hide those extra parenthesis and remap method calls to display as operator. In other words, as with the Python indenting vs. curly braces, the editor could potentially perform a display transformation, to make the code look pretty, while retaining the above boilerplate in the file source code for semantic clarity. In general, the design decision for Copute is to not obfuscate the structure with syntactical sugar, also including do-notation, functions as infix operators, list comprehensions, etc., but to instead allow the editor to display such synactical sugar as a rendering transformation. The advantage being that underlying source code is explicit, and thus widely readable, with verbosity adjustable with rendering transformations. Scala has been criticized as write-only language, because special knowledge is needed for each library that employs varying syntactical sugar. Copute is a minimum common set for the language, then a plethora skinnable rendering sugar.

parametric inheritance. Scala and Copute have the same syntax for variance annotation and parameter type constraint bound (Copute reverses the angle bracket direction). However, Scala requires explicit covariant declaration where Copute may be able to detect it automatically, in an otherwise invariant parameter type, at least because there is no pure function model in Scala.
Parametrized type is superior because it doesn't hide the types and variance assumptions from inheritance declaration. Abstract type.
Use parametrized method, and then with type constraint bound in the subclass. Explicitly Typed Self References.
Use Node<{new()}>, because anonymous type with constructor are each a distinct type.
Todo: we could decide to map ClassType.ClassType to Scala's ClassType#ClassType, and let reference.ClassType follow Scala's semantics.
Inner class.
Use anonymous class type containing no constructor, with multiple inheritance of interface(s) and/or class(es) with no constructor. Compound Type.
constructor as orthogonal subclass. Case classes.
constructor pattern match destructuring. Pattern matching.
Supported. Higher-kinded type.
Scala's object is just syntactical sugar for a global instance of a class with a private constructor. In the case of a companion class, the singleton object's class should be declared to have private access permission. Singleton object.
_ is just syntactical sugar for T <: Any, and any bounds can be put in a function's type parameters. Existential type.
Wrap statement in singleton anonymous function with trailing parenthesis to function call, using explicit or ->. Although more verbose, makes the statements explicit, which is more readable/intuitive for C-like language programmers. The slight increase in verbosity is mitigated by use of -> instead of . Compiler may optimize such a singleton function declaration plus call as inline code without function call. Everything is an expression, e.g. nesting switch-case as expressions.
todo import is scoped.

Haskell

Copute has equivalent expressive power relative to the "Expression Problem" for extension, with following advantages.

Python

Python is lacking fundamental expressive power relative to the "Expression Problem" for extension, because dynamically typed languages do not address such a problem, and also perhaps due to lack of algebraic type pattern matching. Python also has the following disadvantages.

HaXe

Copute was initially inspired by fundamental weaknesses in the otherwise excellent concept of HaXe.

Copute has HaXe equivalent
Pure function none. Implements a pure function, but the pureness invariants are not checked by the compiler.
Function overloading. none
Non-static method type parametrization. none. HaXe has only class type parametrization and for static methods.
Mixin multiple inheritance. none
Orthogonal Maybe type, not automatically unboxed if not checked. none. HaXe defaults types to nullable, which can cause an unchecked exception on every use of every type. Also has platform inconsistent nullable semantics.
No boilerplate dynamic member access. none. HaXe requires verbose reflection API access.
Optional argument with default none. Must either be a constant or null, no support for default constructor of the argument's type, nor for a default which is not a constant.
Useful anonymous structural type, without harmful forms of static duck typing. Useful anonymous structural type and typedef, with erroneous inference of semantics.
No method HaXe has the harmful feature, but Copute does too via , but at least discouraged.
No of exception none. HaXe has the harmful feature.
Typed ordered sequence
(a/k/a tuple)
Employ a class for each class Tuple<A, B, ...> { ... }.
Destructuring sequence
return to local instances
none. (a/k/a HaXe lacks destructured multiple value return from method)
Range-of-integers
(i.e. ordinals)
none. Each range-of-integers type as a class, but the arguments of the construction of an instance is not checked at compile-time so the constructor can throw an exception.
Enum methods. none. Write functions that take the enum as an argument.
parametric inheritance. none. HaXe has no immutable semantics, thus inefficient copying of subclass parametric members to an instance of the superclass parametric type.

Type erasure versus reification

Here follows the Wikipedia comparison for Java's type erasure versus Microsoft C#'s reification, which I have expanded to include Scala's improvements over Java, and Copute's proposed method to obtain full reification via various planned output targets. The rows from the Wikipedia table which seemed unimportant, appear as empty rows below.

Btw, I find this summary of differences between Java and Scala, very useful.

So far, it seems to me that type erasure is more efficient than reification, because it does not require unnecessary multiple runtime versions of generic code, and that the problems with type erasure are because the JVM (Java Virtual Machine) has poorly understood "use-site" variance declaration (versus Copute and Scala's "definitions-site" site variance declaration), and JVM erases the order and number of type parameters and the bounds of the type parameters, so there is much unnecessary casting (i.e. reflection) and other problems.

Type erasure is probably required for higher-kinded types, which are required to do type classes, monads, and pretty much anything with generics generally without massive boilerplate and loss of abstraction.

Java Microsoft C# Scala Copute
Type checks and downcasts are (implicitly) injected into client code (the code referencing the generics). Compared to non-generic code with manual casts, these casts will be the same[11]. But compared to compile-time verified code which would not need runtime casts and checks, these operations represent a performance overhead. Note such casts are not injected when the type parameter has a bound (the type that is erased to) which is the expected type. C#/.NET generics guarantees type-safety and is verified at compile time and no extra checks/casts are necessary at runtime. Hence, generic code will run faster than non-generic code (and type-erased code) which require casts when handling non-generic or type-erased objects. Scala implicitly injected these casts whether it runs on virtual machine is generics ignorant (i.e. requires type erasure), e.g. Java Virtual Machine (JVM), or on a virtual machine which has reification, e.g. Microsoft .Net Copute is a chameleon and these casts will only be implicitly injected when type erasure is required by the output target. And note that dynamically typed language output targets such as JavaScript and Python, do not need casts (although they suffer speed because they do hashtable lookup for each object member access).
Cannot use primitive types as type parameters; instead the developer must use the wrapper type corresponding to the primitive type. This incurs extra performance overhead by requiring boxing and unboxing conversions as well a memory and garbage collection pressure because the wrappers will be heap allocated as opposed to stack allocated. Primitive and value types are allowed as type parameters in generic realizations. At runtime code will be synthesized and compiled for each unique combination of type parameters upon first use. Generics which are realized with primitive/value type do not require boxing/unboxing conversions. Even though all primitive types are classes in Scala, these are implemented as primitive types where possible in the JVM["Step 8"]. Thus, due to type erasure Scala suffers the same boxing performance penalty as Java when a primitive type is used as a type parameter. However, there exist libraries and experimental compiler features to help with optimization but they introduce boilerplate tsuris. Copute is a chameleon and will at least achieve at least the performance of its output target. Additionally, Copute may apply implicit optimizations (that require no boilerplate) to improve performance on output targets that otherwise employ boxing.
Generic exceptions are not allowed[12] and a type parameter cannot be used in a catch clause[13]. Can both define generic exceptions and use those in catch clauses. ? Copute is discouraging, or hopefully eliminating, user code exceptions. Exceptions may be generated implicitly by primitive types, e.g. integer overflow.
Static members are shared across all generic realizations[14] (during type erasure all realizations are folded into a single class). Note this is only a problem for mutable static members, e.g. those not final or a method. Note that it is not allowed to make a static member which is not a function (nor method) and has the type of, or that is parametrized by, a class type parameter, because these would present a type mismatch between two generic realizations. Static members are separate for each generic realization. A generic realization is a unique class. Scala's singleton object is shared across all type parameter realizations of the companion class, and it can not be type parametrized, but each method of a singleton object can be orthogonally parametrized (see next row of this table), which is essentially what is needed. Thus this is only a problem for mutable members of object, e.g. those that are var (not val or def), because they can not be type parametrized. Although it is difficult to think of a case where there is benefit when static members are separate for each type parameter realization (why is a list of string differentiated from a list of integer for a static?), Copute could achieve this on output targets which use type erasure by creating a unique singleton object for each realization, but only necessary for those that have mutable static members. It is not yet decided if there are use cases that justify this, since afaics it is only necessary for a static member which is not a function (nor method) and has the type of, or that is parametrized by, a type parameter, because these would otherwise present a type mismatch between two generic realizations, but mutable statics are bad design.
Type parameters cannot be used in declarations of static fields/methods or in definitions of static inner classes. No restrictions on use of type parameters. Each function (or method) in the singleton object can declare type parameters which are orthogonal to, or duplicates of, any type parameters of the companion class. Any companion class type parameters can be accessed, by inputting an instance of the companion class to the static function (or method), then calling a method in the companion class-- because there is no use for the concrete companion class type parameters without an instance of the companion class. As stated in prior row of this table, mutable static non-functions (a/k/a 'fields') can not be type parametrized, and they can't be allowed because they cause type mismatch between generic realizations (and are undesirable bad design any way). Inner classes are correctly orthogonally parametrized and the type parameters can be specified on each generic realization. Ditto as per Scala, except this is done with 'static' keyword instead of singleton 'object' declaration. It would also be possible to simulate type parametrized mutable static non-functions (a/k/a 'fields'), per the prior row of this table, but probably undesirable.
Cannot create an array where the component type is a generic realization (concrete parameterized type).
object tenPairs =
    new Pair<Integer, String>[10];
A generic realization is a 1st class citizen and can be used as any other class; also an array component.
object tenPairs =
    new Pair<int, string>[10];
"Scala does not know such a restriction, although it uses erasure."
var tenPairs =
    new Array[Pair[Integer, String]](10);
Copute does not have such restriction.
Cannot create an array where the component type is a type parameter.
class GenericArrayTest<T>{
  public <T> T[] returnArray(){
    return new T[10];
  }
}
}
Type parameters represent actual, discrete classes and can be used like any other type within the generic definition.
public class Lookup<TKey, TValue> {
    public TValue[] GetEmptyValues(TKey key) {
        return new TValue[0]; // ok
    }
}
"Scala does not know such a restriction, although it uses erasure."
class GenericArrayTest[T]{
  def returnArray: Array[T] = {
    return new Array[T](10);
  }
}
Copute does not have such restriction.
There is no class literal for a concrete realization of a generic type. Thus instanceof and cast on a parametrized type are impossible.
List<T> o
o instanceOf List<String>
(List<String>)o
A generic realization is an actual class. There is no class literal for a concrete realization of a type parameter. Thus isInstanceOf, asInstanceOf, and pattern matching a parametrized type are impossible.
List[T] o
o.isInstanceOf[List[String]]
o.asInstanceOf[List[String]]
It is difficult to think of a case where there is a benefit to isInstanceOf, asInstanceOf, or pattern matching on a parametrized type, because it would be impossible to know a priori all the possible class literals to expect and this would not be checked at compile-time. An equivalent functionality can be checked at compiled-time by employing function overloading, which is compatible with output targets that do type erasure. Although isInstanceOf and pattern matching could be provided by storing reflection data in each instance, or otherwise providing reflection, it is the implementation of asInstanceOf which would be more complex as it would require casts on every use of the erased type parameter, e.g. T as String erased to Object.
instanceof is not allowed with type parameters or concrete generic realizations. The is and as operators work the same for type parameters as for any other type. See prior row of this table. See prior row of this table.
Cannot create new instances using a type parameter as the type. With a constructor constraint, generic methods or methods of generic classes can create instances of classes which have default constructors. Cannot create new instances using a type parameter as the type. It is poor design to instantiate explicit class literals (i.e. use new), so proper design will have all types implement a static type parametrized factory interface, then any type parameter which is upper bound on that interface, can be instantiated by calling the interface's factory method. This boilerplate could be automated in Copute for every concrete class that has an implicit (i.e. no explicit) or constructor without formal parameters. The concrete class could override factory method to provide custom behavior. Such a solution works with output targets that do type erasure.
The unbounded type(s) of the parametrized type are erased during compilation. Special extensions to reflection must be used to discover the original type. Type information about C# generic types is fully preserved at runtime, and allows complete reflection support as well as instantiation of generic types. The unbounded type(s) of the parametrized type are erased during compilation. It is difficult to think of a case of benefit from reflection for reading the unbounded type(s) of a parametrized type. It could be done if we can think of a justified use case.