Why does wrapping a method in another method stop type mismatch in Scala - using underscore in type parameter...
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
In the following block of code (with both scala 2.11
and 2.12
) the method apply
does not compile, while applyInlined
does.
package blar
trait Bar[T]
class A
class B
class C
trait Exploder[T] {
// Removing explode and changing Foo so that
// flatMap takes no param means it will compile
def explode(product: C): Seq[T]
val bar: Bar[T]
}
case object Exploder1 extends Exploder[A] {
def explode(product: C): Seq[A] = ???
val bar: Bar[A] = ???
}
case object Exploder2 extends Exploder[B] {
def explode(product: C): Seq[B] = ???
val bar: Bar[B] = ???
}
object Thing {
def apply(): Unit = List(Exploder1, Exploder2).foreach {
case exploder: Exploder[_] =>
wrapped(exploder)
}
def applyInlined(): Unit = List(Exploder1, Exploder2).foreach {
case exploder: Exploder[_] =>
flatMap(exploder.explode)(exploder.bar)
}
def flatMap[U: Bar](explode: C => TraversableOnce[U]): Unit = ???
def wrapped[T](exploder: Exploder[T]): Unit =
flatMap(exploder.explode)(exploder.bar)
}
The error message is
[error] .../src/main/scala/blar/Bar.scala:34:42: type mismatch;
[error] found : blar.Bar[_1]
[error] required: blar.Bar[Object]
[error] Note: _1 <: Object, but trait Bar is invariant in type T.
[error] You may wish to define T as +T instead. (SLS 4.5)
[error] flatMap(exploder.explode)(exploder.bar)
[error] ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 4 s, completed 03-Jan-2019 13:43:45
- My main question is why? Is this a bug?
As you can see applyInlined
only differs in that it has inlined the body of the wrapped
method. This means that somehow the extra wrapping of some code in a method has "tricked" the compiler into working.
The other question is can you think of a design/hack that would avoid this kind of thing without making
Blar
covariant? How can I make the inlined version compile? Can I do it with anasInstanceOf
What is scala inferring the type to be in order to call
wrapped
without an explicit type param?
scala types covariance scalac scala-compiler
add a comment |
In the following block of code (with both scala 2.11
and 2.12
) the method apply
does not compile, while applyInlined
does.
package blar
trait Bar[T]
class A
class B
class C
trait Exploder[T] {
// Removing explode and changing Foo so that
// flatMap takes no param means it will compile
def explode(product: C): Seq[T]
val bar: Bar[T]
}
case object Exploder1 extends Exploder[A] {
def explode(product: C): Seq[A] = ???
val bar: Bar[A] = ???
}
case object Exploder2 extends Exploder[B] {
def explode(product: C): Seq[B] = ???
val bar: Bar[B] = ???
}
object Thing {
def apply(): Unit = List(Exploder1, Exploder2).foreach {
case exploder: Exploder[_] =>
wrapped(exploder)
}
def applyInlined(): Unit = List(Exploder1, Exploder2).foreach {
case exploder: Exploder[_] =>
flatMap(exploder.explode)(exploder.bar)
}
def flatMap[U: Bar](explode: C => TraversableOnce[U]): Unit = ???
def wrapped[T](exploder: Exploder[T]): Unit =
flatMap(exploder.explode)(exploder.bar)
}
The error message is
[error] .../src/main/scala/blar/Bar.scala:34:42: type mismatch;
[error] found : blar.Bar[_1]
[error] required: blar.Bar[Object]
[error] Note: _1 <: Object, but trait Bar is invariant in type T.
[error] You may wish to define T as +T instead. (SLS 4.5)
[error] flatMap(exploder.explode)(exploder.bar)
[error] ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 4 s, completed 03-Jan-2019 13:43:45
- My main question is why? Is this a bug?
As you can see applyInlined
only differs in that it has inlined the body of the wrapped
method. This means that somehow the extra wrapping of some code in a method has "tricked" the compiler into working.
The other question is can you think of a design/hack that would avoid this kind of thing without making
Blar
covariant? How can I make the inlined version compile? Can I do it with anasInstanceOf
What is scala inferring the type to be in order to call
wrapped
without an explicit type param?
scala types covariance scalac scala-compiler
2
@LuisMiguelMejíaSuárez Because of[U: Bar]
,flatMap
expects a second, implicit argument.
– Andrey Tyukin
Jan 3 at 14:34
@AndreyTyukin Ah yes, of course - my bad.
– Luis Miguel Mejía Suárez
Jan 3 at 14:53
add a comment |
In the following block of code (with both scala 2.11
and 2.12
) the method apply
does not compile, while applyInlined
does.
package blar
trait Bar[T]
class A
class B
class C
trait Exploder[T] {
// Removing explode and changing Foo so that
// flatMap takes no param means it will compile
def explode(product: C): Seq[T]
val bar: Bar[T]
}
case object Exploder1 extends Exploder[A] {
def explode(product: C): Seq[A] = ???
val bar: Bar[A] = ???
}
case object Exploder2 extends Exploder[B] {
def explode(product: C): Seq[B] = ???
val bar: Bar[B] = ???
}
object Thing {
def apply(): Unit = List(Exploder1, Exploder2).foreach {
case exploder: Exploder[_] =>
wrapped(exploder)
}
def applyInlined(): Unit = List(Exploder1, Exploder2).foreach {
case exploder: Exploder[_] =>
flatMap(exploder.explode)(exploder.bar)
}
def flatMap[U: Bar](explode: C => TraversableOnce[U]): Unit = ???
def wrapped[T](exploder: Exploder[T]): Unit =
flatMap(exploder.explode)(exploder.bar)
}
The error message is
[error] .../src/main/scala/blar/Bar.scala:34:42: type mismatch;
[error] found : blar.Bar[_1]
[error] required: blar.Bar[Object]
[error] Note: _1 <: Object, but trait Bar is invariant in type T.
[error] You may wish to define T as +T instead. (SLS 4.5)
[error] flatMap(exploder.explode)(exploder.bar)
[error] ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 4 s, completed 03-Jan-2019 13:43:45
- My main question is why? Is this a bug?
As you can see applyInlined
only differs in that it has inlined the body of the wrapped
method. This means that somehow the extra wrapping of some code in a method has "tricked" the compiler into working.
The other question is can you think of a design/hack that would avoid this kind of thing without making
Blar
covariant? How can I make the inlined version compile? Can I do it with anasInstanceOf
What is scala inferring the type to be in order to call
wrapped
without an explicit type param?
scala types covariance scalac scala-compiler
In the following block of code (with both scala 2.11
and 2.12
) the method apply
does not compile, while applyInlined
does.
package blar
trait Bar[T]
class A
class B
class C
trait Exploder[T] {
// Removing explode and changing Foo so that
// flatMap takes no param means it will compile
def explode(product: C): Seq[T]
val bar: Bar[T]
}
case object Exploder1 extends Exploder[A] {
def explode(product: C): Seq[A] = ???
val bar: Bar[A] = ???
}
case object Exploder2 extends Exploder[B] {
def explode(product: C): Seq[B] = ???
val bar: Bar[B] = ???
}
object Thing {
def apply(): Unit = List(Exploder1, Exploder2).foreach {
case exploder: Exploder[_] =>
wrapped(exploder)
}
def applyInlined(): Unit = List(Exploder1, Exploder2).foreach {
case exploder: Exploder[_] =>
flatMap(exploder.explode)(exploder.bar)
}
def flatMap[U: Bar](explode: C => TraversableOnce[U]): Unit = ???
def wrapped[T](exploder: Exploder[T]): Unit =
flatMap(exploder.explode)(exploder.bar)
}
The error message is
[error] .../src/main/scala/blar/Bar.scala:34:42: type mismatch;
[error] found : blar.Bar[_1]
[error] required: blar.Bar[Object]
[error] Note: _1 <: Object, but trait Bar is invariant in type T.
[error] You may wish to define T as +T instead. (SLS 4.5)
[error] flatMap(exploder.explode)(exploder.bar)
[error] ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 4 s, completed 03-Jan-2019 13:43:45
- My main question is why? Is this a bug?
As you can see applyInlined
only differs in that it has inlined the body of the wrapped
method. This means that somehow the extra wrapping of some code in a method has "tricked" the compiler into working.
The other question is can you think of a design/hack that would avoid this kind of thing without making
Blar
covariant? How can I make the inlined version compile? Can I do it with anasInstanceOf
What is scala inferring the type to be in order to call
wrapped
without an explicit type param?
scala types covariance scalac scala-compiler
scala types covariance scalac scala-compiler
edited Jan 4 at 12:41
samthebest
asked Jan 3 at 13:56
samthebestsamthebest
19.9k1475113
19.9k1475113
2
@LuisMiguelMejíaSuárez Because of[U: Bar]
,flatMap
expects a second, implicit argument.
– Andrey Tyukin
Jan 3 at 14:34
@AndreyTyukin Ah yes, of course - my bad.
– Luis Miguel Mejía Suárez
Jan 3 at 14:53
add a comment |
2
@LuisMiguelMejíaSuárez Because of[U: Bar]
,flatMap
expects a second, implicit argument.
– Andrey Tyukin
Jan 3 at 14:34
@AndreyTyukin Ah yes, of course - my bad.
– Luis Miguel Mejía Suárez
Jan 3 at 14:53
2
2
@LuisMiguelMejíaSuárez Because of
[U: Bar]
, flatMap
expects a second, implicit argument.– Andrey Tyukin
Jan 3 at 14:34
@LuisMiguelMejíaSuárez Because of
[U: Bar]
, flatMap
expects a second, implicit argument.– Andrey Tyukin
Jan 3 at 14:34
@AndreyTyukin Ah yes, of course - my bad.
– Luis Miguel Mejía Suárez
Jan 3 at 14:53
@AndreyTyukin Ah yes, of course - my bad.
– Luis Miguel Mejía Suárez
Jan 3 at 14:53
add a comment |
1 Answer
1
active
oldest
votes
I don't know. Experimental evidence shows that it has something to do with the presence / absence of the explicit
[Exploder[_]]
type annotation onList
. WithoutList[Exploder[_]]
, the inferred type of the list becomes
List[Product with Serializable with Exploder[_ >: B with A <: Object]]
and for whatever reason, it somehow messes up the subsequent pattern matching. The
B with A
lower bound looks a little suspicious to me, but I can't explain why it would interfere with the pattern matching.
No, fortunately, no
asInstanecOf
s are required. Both of the following variants work fine:
def applyInlined: Unit = List[Exploder[_]](Exploder1, Exploder2).foreach {
case exploder: Exploder[t] => {
flatMap(exploder.explode)(exploder.bar)
}
}
same with a separately declared implicit variable (note that now you have some type
t
to refer to):
def applyInlined2: Unit = List[Exploder[_]](Exploder1, Exploder2).foreach {
case exploder: Exploder[t] => {
implicit val bar: Bar[t] = exploder.bar
flatMap(exploder.explode)
}
}
See Type parameter inference in patterns for more about the
[t]
-part.
I assume it's some synthetic dummy type
_1
.
Thanks Andrey, especially for answer 2, now I can inline that useless method. Would be interesting to understand "for whatever reason, it somehow messes up the subsequent pattern matching".
– samthebest
Jan 4 at 16:40
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54023745%2fwhy-does-wrapping-a-method-in-another-method-stop-type-mismatch-in-scala-using%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
I don't know. Experimental evidence shows that it has something to do with the presence / absence of the explicit
[Exploder[_]]
type annotation onList
. WithoutList[Exploder[_]]
, the inferred type of the list becomes
List[Product with Serializable with Exploder[_ >: B with A <: Object]]
and for whatever reason, it somehow messes up the subsequent pattern matching. The
B with A
lower bound looks a little suspicious to me, but I can't explain why it would interfere with the pattern matching.
No, fortunately, no
asInstanecOf
s are required. Both of the following variants work fine:
def applyInlined: Unit = List[Exploder[_]](Exploder1, Exploder2).foreach {
case exploder: Exploder[t] => {
flatMap(exploder.explode)(exploder.bar)
}
}
same with a separately declared implicit variable (note that now you have some type
t
to refer to):
def applyInlined2: Unit = List[Exploder[_]](Exploder1, Exploder2).foreach {
case exploder: Exploder[t] => {
implicit val bar: Bar[t] = exploder.bar
flatMap(exploder.explode)
}
}
See Type parameter inference in patterns for more about the
[t]
-part.
I assume it's some synthetic dummy type
_1
.
Thanks Andrey, especially for answer 2, now I can inline that useless method. Would be interesting to understand "for whatever reason, it somehow messes up the subsequent pattern matching".
– samthebest
Jan 4 at 16:40
add a comment |
I don't know. Experimental evidence shows that it has something to do with the presence / absence of the explicit
[Exploder[_]]
type annotation onList
. WithoutList[Exploder[_]]
, the inferred type of the list becomes
List[Product with Serializable with Exploder[_ >: B with A <: Object]]
and for whatever reason, it somehow messes up the subsequent pattern matching. The
B with A
lower bound looks a little suspicious to me, but I can't explain why it would interfere with the pattern matching.
No, fortunately, no
asInstanecOf
s are required. Both of the following variants work fine:
def applyInlined: Unit = List[Exploder[_]](Exploder1, Exploder2).foreach {
case exploder: Exploder[t] => {
flatMap(exploder.explode)(exploder.bar)
}
}
same with a separately declared implicit variable (note that now you have some type
t
to refer to):
def applyInlined2: Unit = List[Exploder[_]](Exploder1, Exploder2).foreach {
case exploder: Exploder[t] => {
implicit val bar: Bar[t] = exploder.bar
flatMap(exploder.explode)
}
}
See Type parameter inference in patterns for more about the
[t]
-part.
I assume it's some synthetic dummy type
_1
.
Thanks Andrey, especially for answer 2, now I can inline that useless method. Would be interesting to understand "for whatever reason, it somehow messes up the subsequent pattern matching".
– samthebest
Jan 4 at 16:40
add a comment |
I don't know. Experimental evidence shows that it has something to do with the presence / absence of the explicit
[Exploder[_]]
type annotation onList
. WithoutList[Exploder[_]]
, the inferred type of the list becomes
List[Product with Serializable with Exploder[_ >: B with A <: Object]]
and for whatever reason, it somehow messes up the subsequent pattern matching. The
B with A
lower bound looks a little suspicious to me, but I can't explain why it would interfere with the pattern matching.
No, fortunately, no
asInstanecOf
s are required. Both of the following variants work fine:
def applyInlined: Unit = List[Exploder[_]](Exploder1, Exploder2).foreach {
case exploder: Exploder[t] => {
flatMap(exploder.explode)(exploder.bar)
}
}
same with a separately declared implicit variable (note that now you have some type
t
to refer to):
def applyInlined2: Unit = List[Exploder[_]](Exploder1, Exploder2).foreach {
case exploder: Exploder[t] => {
implicit val bar: Bar[t] = exploder.bar
flatMap(exploder.explode)
}
}
See Type parameter inference in patterns for more about the
[t]
-part.
I assume it's some synthetic dummy type
_1
.
I don't know. Experimental evidence shows that it has something to do with the presence / absence of the explicit
[Exploder[_]]
type annotation onList
. WithoutList[Exploder[_]]
, the inferred type of the list becomes
List[Product with Serializable with Exploder[_ >: B with A <: Object]]
and for whatever reason, it somehow messes up the subsequent pattern matching. The
B with A
lower bound looks a little suspicious to me, but I can't explain why it would interfere with the pattern matching.
No, fortunately, no
asInstanecOf
s are required. Both of the following variants work fine:
def applyInlined: Unit = List[Exploder[_]](Exploder1, Exploder2).foreach {
case exploder: Exploder[t] => {
flatMap(exploder.explode)(exploder.bar)
}
}
same with a separately declared implicit variable (note that now you have some type
t
to refer to):
def applyInlined2: Unit = List[Exploder[_]](Exploder1, Exploder2).foreach {
case exploder: Exploder[t] => {
implicit val bar: Bar[t] = exploder.bar
flatMap(exploder.explode)
}
}
See Type parameter inference in patterns for more about the
[t]
-part.
I assume it's some synthetic dummy type
_1
.
edited Jan 3 at 16:51
answered Jan 3 at 14:55
Andrey TyukinAndrey Tyukin
30.7k42351
30.7k42351
Thanks Andrey, especially for answer 2, now I can inline that useless method. Would be interesting to understand "for whatever reason, it somehow messes up the subsequent pattern matching".
– samthebest
Jan 4 at 16:40
add a comment |
Thanks Andrey, especially for answer 2, now I can inline that useless method. Would be interesting to understand "for whatever reason, it somehow messes up the subsequent pattern matching".
– samthebest
Jan 4 at 16:40
Thanks Andrey, especially for answer 2, now I can inline that useless method. Would be interesting to understand "for whatever reason, it somehow messes up the subsequent pattern matching".
– samthebest
Jan 4 at 16:40
Thanks Andrey, especially for answer 2, now I can inline that useless method. Would be interesting to understand "for whatever reason, it somehow messes up the subsequent pattern matching".
– samthebest
Jan 4 at 16:40
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54023745%2fwhy-does-wrapping-a-method-in-another-method-stop-type-mismatch-in-scala-using%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
@LuisMiguelMejíaSuárez Because of
[U: Bar]
,flatMap
expects a second, implicit argument.– Andrey Tyukin
Jan 3 at 14:34
@AndreyTyukin Ah yes, of course - my bad.
– Luis Miguel Mejía Suárez
Jan 3 at 14:53