Scala is an expressive statically typed functional programming language that runs on the Java Virtual Machine (JVM). It has advanced type-level programming features, which allow you to perform computation at the type level and also help in writing more robust and statically checked code. On the other hand, Idris and Agda are two prominent languages with full dependent types support, meaning that types can be dependent on values, and values can depend on types.
Before we compare Scala’s type-level programming features to those in Idris and Agda, let’s understand what dependent types are:
A dependent type is a type that depends on a value, which allows us to define precise contracts between the different parts of our program. In a language with dependent types, we can express properties about our programs directly in the type system and get compile-time guarantees about our code’s correctness.
Scala’s type-level programming features are quite powerful but not as expressive as languages like Idris and Agda when it comes to dependent types. Let’s discuss some of these differences.
1. Type-level functions and computation:
Scala has implicit resolution, type classes, and "Path-dependent types", which allow you to create type-level functions and computations to some extent. However, the type system in Scala is not as expressive as in languages like Idris or Agda. In Idris and Agda, we can have full-featured functions at the type level and use recursion, pattern matching, and all the other standard features of the language.
2. Dependent types and proof terms:
While Scala has support for path-dependent types, which allow relatively simple dependent types, it does not have full support like Idris or Agda. In Idris and Agda, dependent types can depend on arbitrary values, and proof terms can be manipulated as regular values. This allows for more expressive and precise contracts between functions and their arguments.
3. Propositions as types:
The "propositions as types" correspondence is central to languages like Idris and Agda, where types can encode properties and proofs, effectively using the type system to perform verification at compile-time. While Scala has some support for encoding properties as types through its advanced type and implicits systems, it does not embrace the full "propositions as types" concept like Idris and Agda.
4. Higher-kinded types:
Scala supports higher-kinded types, which are types with type parameters that themselves take type parameters. This allows expressive abstractions and advanced techniques like type level computation. Idris and Agda support these features seamlessly as part of their dependent type systems.
5. Language-level features:
While Scala has a few built-in features specifically tailored for type-level programming, such as type classes, type projections, and singleton types, Idris and Agda are designed from the ground up to support dependent types.
In conclusion, Scala’s type-level programming features are powerful and expressive but still lack the full dependent types support found in languages like Idris or Agda. If your primary goal is to work with true dependent types, Idris or Agda may be more suitable. However, Scala’s type-level programming features can still be used effectively to help build robust and statically checked code.