cda-group / arc

Programming Language for Continuous Deep Analytics
https://cda-group.github.io/arc/
44 stars 6 forks source link

RFC: Generics syntax #330

Closed segeljakt closed 1 year ago

segeljakt commented 2 years ago

Languages like Haskell distinguish nominal types from type parameters by writing the former as uppercase and latter as lowercase.

class Num a where
    (+) :: a -> a -> a

instance Num Int where
    (+) x y = x + y

Rust on the other hand introduces a binding site for generics:

trait Num<T> {
    fn add(a: T, b: T) -> T;
}

impl Num<i32> {
    fn add(a: i32, b: i32) -> i32 {
         a + b
    }
}

The benefit of Haskell's syntax is that you don't need binding sites in instances, e.g., in Rust you might need:

impl<T> Foo<T> { ... }

But in Haskell, it's just:

instance Foo a where
    ...

Could we support a generics syntax similar to Haskell's? I am curious if it would result in less code. The following is the same as before, except that we now need I32 instead of i32:

# Before
class Num[T] {
    def add(T, T) -> T;
}

instance Num[i32] {
    fn add(a, b) {
         a + b
    }
}

# After
class Num[a] {
    def add(a, a) -> a;
}

instance Num[I32] {
    fn add(x, y) {
         x + y
    }
}

But this would be briefer:

# Before
instance[T] Foo[T] { ... }
# After
instance Foo[a] { ... }

To express constraints on type parameters, you could write:

instance Foo[a] where a: Display { ... }