You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I expect that, because foo2 and foo4 compile (adding a lower bound or adding an upper bound to an existential doesn't interfere with typechecking) foo3 should also compile (if a lower bound is valid and an upper bound is valid, the same program should still be valid).
Note that T forSome { type T ; type X >: Box[T] <: B } is valid for typechecking. I wrote it trying to solve a problem posed by @lihaoyi:
classBox[T](t: T)
classCall[B<:Box[_]](ub: ???) { defvalue:B=Box(ub) }
objectFooextendsCall[Box[Int]](1) // How to make this typecheck?objectBarextendsCall[Box[Int]]("not an int") // And this fail?
My idea was to use an existential to posit some type T such that Box[T] <: B. I know that one can replace evidence like implicit ev: A <:< B with a type parameter [X >: A <: B], making the method only callable if A <: B, and I figured this technique can be applied to existentials as well. The following typechecks:
valx:Box[Int] =Box(1)
objectXextendsCall[x.type](1)
objectYextendsCall[Box[Int]]("not an int")
The problem is that one cannot implement def value: B with this signature, due to the unique double-bounded existential failure:
@classCall[B<:Box[_]](b: (T forSome { typeT ; typeX>:Box[T] <:B })) {
>defvalue:B= {
>valoriginal:Box[T forSome { typeT ; typeX>:Box[T] <:B }] =newBox[T forSome { typeT ; typeX>:Box[T] <:B }]
>valsimplifyToX: (X forSome { typeT ; typeX>:Box[T] <:B }) = original
>valsimplifyToB:B= simplifyToX
> simplifyToB
> }
> }
cmd1.sc:3:typemismatch;
found : (some other)T(in value original) where type (some other)T(in value original)
required: T(in value original) forSome { typeT(in value original); typeX>: ammonite.$sess.cmd0.Box[T(in value original)] <:B }
valoriginal:Box[T forSome { typeT ; typeX>:Box[T] <:B }] =newBox[T forSome { typeT ; typeX>:Box[T] <:B }](b)
^
cmd1.sc:3:typemismatch;
found : ammonite.$sess.cmd0.Box[(some other)T(in value original) forSome { type (some other)T(in value original); typeX>: ammonite.$sess.cmd0.Box[(some other)T(in value original)] <:B }]
required: ammonite.$sess.cmd0.Box[T(in value original) forSome { typeT(in value original); typeX>: ammonite.$sess.cmd0.Box[T(in value original)] <:B }]
valoriginal:Box[T forSome { typeT ; typeX>:Box[T] <:B }] =newBox[T forSome { typeT ; typeX>:Box[T] <:B }](b)
^
cmd1.sc:4:typemismatch;
found : ammonite.$sess.cmd0.Box[T(in value original) forSome { typeT(in value original); typeX>: ammonite.$sess.cmd0.Box[T(in value original)] <:B }]
required: X forSome { typeT(in value simplifyToX); typeX>: ammonite.$sess.cmd0.Box[T(in value simplifyToX)] <:B }
valsimplifyToX: (X forSome { typeT ; typeX>:Box[T] <:B }) = original
^
CompilationFailed
Yet foo5 shows that the original and simplifyToX steps should work, and (X forSome { type X <: U }) means that simplifyToB should work (as it seems to in this example).
The text was updated successfully, but these errors were encountered:
Reproduction steps
Scala version: 2.13.10
Problem
I expect that, because
foo2
andfoo4
compile (adding a lower bound or adding an upper bound to an existential doesn't interfere with typechecking)foo3
should also compile (if a lower bound is valid and an upper bound is valid, the same program should still be valid).Note that
T forSome { type T ; type X >: Box[T] <: B }
is valid for typechecking. I wrote it trying to solve a problem posed by @lihaoyi:My idea was to use an existential to posit some type
T
such thatBox[T] <: B
. I know that one can replace evidence likeimplicit ev: A <:< B
with a type parameter[X >: A <: B]
, making the method only callable ifA <: B
, and I figured this technique can be applied to existentials as well. The following typechecks:and the following fail:
The problem is that one cannot implement
def value: B
with this signature, due to the unique double-bounded existential failure:Yet
foo5
shows that theoriginal
andsimplifyToX
steps should work, and(X forSome { type X <: U })
means thatsimplifyToB
should work (as it seems to in this example).The text was updated successfully, but these errors were encountered: