0

Is the following expected behavior or bug in Scala?

CASE 1:

class X[T1, T2]
class XExt[T1, T2] extends X[T1, T2]
class Y[T[t1] <: X[t1, _]]
class YExt extends Y[XExt]

results in Error: XExt takes two type parameters, expected: one

class YExt extends Y[XExt]
                     ^

But the following runs ok:

class X[T1, T2]
class XExt[T1, T2] extends X[T1, T2]
class Y[T[t1, t2] <: X[t1, t2]]
class YExt extends Y[XExt]

Minimizing the number of params could simplify code like type params: type T[t1] <: X[t1, _].

CASE 2:

class X[T1, T2]
class Y[T[t1, t2] <: X[t1, t2]]
class Z[T <: Y[_]]

results in Error: _$1 takes no type parameters, expected: two

class Z[T <: Y[_]]
               ^

But how to avoid defining Y parameters if i do not require them? Like in:

class X[T1, T2]
class Y[T <: X[_, _]]
class Z[T <: Y[_]]

CASE 3:

trait A[T]
trait B[T[t] <: A[t]]
trait AExt extends A[Int]
trait BExt extends B[AExt]

results in Error: AExt takes no type parameters, expected: one

trait BExt extends B[AExt]
                     ^

But why compiler requests one parameter if it's already supplied? It seems a contradiction. And how to subclass B?


That behavior is observed in IntelliJ Scala plugin and Eclipse Scala IDE. So it's probably the Scala compiler functioning.

3
  • 1
    I don't think you can, being Y[_] a nested higher kind with a constraint you need to provide the compile enough evidence that you are respecting that constraint: class Z[S[t1, t2] <: X[t1,t2], T <: Y[S]]. Commented Sep 20, 2014 at 7:12
  • @Ende Neu: Yes but constraint of Y[T] is same. T still has same bounds. I don't see any reason to specify T if i do not require that. And please look CASE 3. I've just added it. Commented Sep 21, 2014 at 5:47
  • No, T has not the same bound, the T in the class and the one in the second case are two different T, only because they have the same letter doesn't mean that they are related. Commented Sep 21, 2014 at 6:48

2 Answers 2

1

Case 1: you said Y takes a type with 1 param, but you gave it a type with two.

Case 2: Similar, try Z[T <: Y[_[_,_]]]

Case 3: You said B takes a type with 1 param, but you gave it a type with two.

No bug, problem lies between keyboard and chair. What are actually trying to do? I.e. give examples, including concrete implementations, then maybe people can help more.

Sign up to request clarification or add additional context in comments.

1 Comment

Short answer does not always means correct answer. But thanks for try. Answer 1: You can declare " type T[t1] <: X[t1, _] ". What is the principal barrier not to do same in generic parameter declaration? Answer 2: Did you try that you suggest? ("Wrong top statement declaration") Answer 3: None of CASE 3 expressions deals with two params. Indeed CASE 3 is most strange. Seems AExt meets the constraint T[t] <: A[t] where t is Int. If you replace generics to abstract types, all those expressions will be compiled with no errors.
0

The cause of misunderstanding is really in mixing the notion of abstract type and generic parameter. Erroneous assumption was that type parameters and generic parameters are equal in rules of constraints. See below. T1 and T2 of class Z are equivalent. But in ZExt they can be defined with class XExt1 and XExt2 which have different number of params. The second param of XExt2 is just ignored. What i expected is that implementing the same logic with generics will allow the same syntax. I.e. Z1 will accept XExt1 as well as XExt2 (like T1 and T2 in Z). But It accepts only XExt1. Placing XExt2 as param results in error.

And honestly still do not understand why not give generics the freedom of types. I.e. why not let XExt2 be the param of Z1, allowing compiler to infer XExt2 param types and just ignore it's second param.

class X[T1, T2]
class XExt1[T1] extends X[T1, Int]
class XExt2[T1, T2] extends X[T1, T2]

class Z {
    type T1[t] <: X[t, _]
    type T2[t] <: X[t, _]
}
class ZExt extends Z {
    type T1[t] = XExt1[t]
    type T2[t] = XExt2[t,_]
}

// But...
class Z1[T[t] <: X[t, _]]
class ZExt1 extends Z1[XExt1]
class ZExt2 extends Z1[XExt2] // Error: XExt2 takes two type parameters, expected: one

Answers on cases:

CASE 1:

Class that extends class Y should exactly meet the T[t] (with one param) that is, for example:

class X[T1, T2]
class XExt[T1] extends X[T1, Int]
class Y[T[t1] <: X[t1, _]]
class YExt extends Y[XExt]

CASE 2:

As @Ende Neu mentioned extra param that meets constraint T[t1,t2] of class Y does its job:

class X[T1, T2]
class Y[T[t1, t2] <: X[t1, t2]]
class Z[S[t1, t2] <: X[t1,t2], T <: Y[S]]

Unfortunately T[t1,t2] cant be described with underscore syntax as @samthebest suggests. Compiler warns with "Wrong top statement declaration":

class Z[T <: Y[_[_, _]]]

CASE 3:

The same problem as in CASE 1. AExt should have one param. For example:

trait A[T]
trait B[T[t] <: A[t]]
trait AExt[T] extends A[T]
trait BExt[T] extends B[AExt]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.