Scala 3 type inference related issue
Hi I don't know how to explain it in short and I'm also not sure whether it's a Scala3 issue. I reproduced it with the scala-cli. If you have it installed have a look at this gist. There are 2 flies and each has a Main method in different packages. You can run them with either
scala-cli https://gist.github.com/agilesteel/05482df2e1f420f762dec7696088552d -M good.Main
or
scala-cli https://gist.github.com/agilesteel/05482df2e1f420f762dec7696088552d -M bad.Main
The Good.scala file in there has no dependencies on cats-core. I defined my own trait Semigroup and my own instance for Option. I also defined a Maybe ADT with the new enum keyword and an instance for it as well.
enum Maybe[+A]:
case Just(a: A)
case Nothing
I noticed 2 things:
-
Some(1) combine Some(2)compiles and works even though my instance is forOption. I don't have an instance forSome, which is surprising. So we don't need.someanymore?! -
Maybe.Just(1) combine Maybe.Just(2)compiles and works as expected since theenumkeyword generates factories which return theMaybetype instead of theMaybe.Justtype (as opposed to manual ADTs in Scala 2 for instance).
The Bad.scala file in there has a dependency on cats-core (2.6.1 but I doubt that the version matters much) and therefore I used the Semigroup from cats. I found the following:
Maybe.Just(1) combine Maybe.Just(2) // does not compile BUT IT SHOULD!
[error] ./Bad.scala:24:11: value combine is not a member of bad.Maybe.Just[Int]
[error] println(Maybe.Just(1) combine Maybe.Just(2)) // does NOT compile
[error]
however
val maybe = Maybe.Just(1) // notice that there is no type ascription or any other type information
maybe combine Maybe.Just(2) // compiles!!!
I used Scala 3.1.0 but other Scala 3.x versions behaved the same.
My expectation is that at least the Maybe examples should compile, right? Why the Option examples work in Good.scala is a mystery to me, but I guess this one is not a cats issue.
I also created this issue https://github.com/lampepfl/dotty/issues/13948
I suggest you include the complete, exact error message that the compiler is emitting.
Thx, done.
I removed my comments from before as it was a misunderstanding of the whole context - scala 3 style extensions seem to improve selection of extension methods
@bishabosha cool so does this mean that this issue becomes a feature request/improvement to encode typeclasses in cats differently (i.e by using the Scala 3 style extensions)?
On the other hand the different widening based on whether sth is in a val or inlined remains weird. It doesn't seem like intentional behavior of Scala3.
this comment might be off-topic but - @agilesteel enum widening is intentionally only when it is the result of some definition, maybe this scope could be increased to more places, it depends on the use case - but it should stay possible to keep the type narrow if required
but it should stay possible to keep the type narrow if required
Isn't it enough that it's possible to keep the type narrow via new Maybe.Just(1) as opposed to Maybe.Just(1)?