cats icon indicating copy to clipboard operation
cats copied to clipboard

Scala 3 type inference related issue

Open agilesteel opened this issue 4 years ago • 6 comments

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:

  1. Some(1) combine Some(2) compiles and works even though my instance is for Option. I don't have an instance for Some, which is surprising. So we don't need .some anymore?!
  2. Maybe.Just(1) combine Maybe.Just(2) compiles and works as expected since the enum keyword generates factories which return the Maybe type instead of the Maybe.Just type (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

agilesteel avatar Nov 14 '21 21:11 agilesteel

I suggest you include the complete, exact error message that the compiler is emitting.

SethTisue avatar Nov 14 '21 21:11 SethTisue

Thx, done.

agilesteel avatar Nov 14 '21 21:11 agilesteel

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 avatar Nov 15 '21 16:11 bishabosha

@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.

agilesteel avatar Nov 15 '21 16:11 agilesteel

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

bishabosha avatar Nov 15 '21 16:11 bishabosha

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)?

agilesteel avatar Nov 15 '21 18:11 agilesteel