Curried type "does not take type parameters"

561 views Asked by At

I wanted to make a type that I could use to verify if a tuple is homogenous. I wrote this, which should ensure that all elements of T are equal to X (Scastie):

type Homogenous[X] = [T <: Tuple] =>> T match {
  case EmptyTuple => DummyImplicit
  case X *: t => Homogenous[X][t] //Doesn't work
  case _ => Nothing
}

def f[T <: Tuple : Homogenous[String]](t: T) = ???

For whatever reason, the third line doesn't compile, with this error:

Homogenous[X] does not take type parameters

However, if I make Homogenous take 2 parameters, it compiles, but I can't use a context bound anymore (Scastie).

type Homogenous[X, T <: Tuple] = T match {
  case EmptyTuple => DummyImplicit
  case X *: t => Homogenous[X, t]
  case _ => Nothing
}

I don't understand why this happens. It's not as if the lambda [T] =>> is only being returned from a specific case of the match type, so the compiler should realize that Homogenous[X] always takes a parameter. Is this a bug or am I doing something wrong, and is there a fix/workaround?

1

There are 1 answers

1
Dmytro Mitin On

Looks like a bug or underimplemented feature.

As a workaround try

trait Hom[X] {
  type Rec[T <: Tuple] = T match {
    case EmptyTuple => DummyImplicit
    case X *: t => Rec[t] 
    case _ => Nothing
  }
}

type Homogenous[X] = [T <: Tuple] =>> Hom[X]#Rec[T]

Maybe connected with

https://contributors.scala-lang.org/t/multiple-type-parameter-lists-in-dotty-si-4719

https://github.com/scala/bug/issues/4719