> Can you elaborate a bit on the sort of code which used to compile but which
> now will not do so?
There are a two indications, which when combined make it likely that
your code will break:
1) Use of `Free`, `IO`, `Trampoline` and related constructs, or monad
transformers.
2) Use of ADTs without smart constructors or with variance.
While I think the first indication is clear, let me elaborate on the
second one.
A somewhat "daily" occurrence of a related problem:
list.foldLeft(Nil)(...)
where `Nil.type` gets inferred as return type of your fold. Same thing
will happen if you have, say
IO { ... Nil }
then that's an `IO[Nil.type]` which, due to lack of variance in `IO`,
not be automatically up-casted to `IO[List[Whatever]]`. The fix is the
same as in the `foldLeft` example:
list.foldLeft[List[Int]](Nil)(...)
list.foldLeft(Nil: List[Int])(...)
list.foldLeft(List.empty[Int])(...)
Another example: assume you have an `OptionT[List, Left[String,
Nothing]]`. Now, you can write:
value: Option[List, Either[String, Int]]
that's not possible any more. Instead, you'd need [*]:
value.map(x => x: Either[String, Int])
When using scalaz, it's very likely that you use things like
3.some
"foo".left[Int]
already, so in these cases you won't notice a different.
The final example is when you define your own data types with variance,
as already outlined in my original mail:
trait Foo[+A] {
def frobnicate: OptionT[List, A] = ...
}
As I said, there are multiple strategies to solve that, but I completely
forgot number 3 which Miles added.
Does that help?
> I really don't think that scalaz should be making other major changes so
> soon after the v7 upgrade pain. If it's source-compatible (or trivial to
> modify), fine, otherwise, please no.
I'm completely with you on that point. The first measure in that
direction is, as you know, binary compatibility in the 7.0.x series. In
the 7.1.x series, I plan to introduce some (non-breaking) changes which
will improve the bincompat story even more.
About source compatibility: We try to keep the list of breaking changes
at a minimum, as you can see here:
<
https://github.com/scalaz/scalaz/wiki/7.1.0-M1#incompatible-changes>.
We're at least going to have one deprecation cycle if possible.
Now, about source compatibility when there is no way for a deprecation
cycle (as it is here in the case of variance). The preceding pull
request [#328] doesn't break anything, so that's good.
Of course, we can discuss whether we should postpone this to 7.2.
However, we *need* to do something about it.
[#328]:
https://github.com/scalaz/scalaz/pull/328
[*] I guess we could add a function to `FunctorOps`:
def up[B >: A]: F[B] = self.map(x => x: B)
Then it'd look like:
value.up[Either[String, Int]]