Tested with 2.13, but I presume it's been like that since 2.12 and I just had not encountered this type of problem before:
trait Extractor[-X, +Y] {
def optional :X => Option[Y] = apply
def apply(x :X) :Option[Y]
def andThen[Z](extractor :Extractor[Y, Z]) :Extractor[X, Z] = {
val first = optional; val second = extractor.optional
Extractor { x :X => first(x).flatMap(second) }
}
def andThen[Z](req :Y => Z) :Extractor[X, Z] = {
val first = optional
Extractor { x :X => first(x).map(req) }
}
def compose[W](extractor :Extractor[W, X]) :Extractor[W, Y] = extractor andThen this
def compose[W](req :W => X) :Extractor[W, Y] = Extractor(req andThen optional)
}
Scalac has a cryptic complaint about the implementation of the first compose:
Error:(44, 31) type mismatch;
found : net.noresttherein.oldsql.morsels.Extractor[X,Y]
required: W => ?
def compose[W](extractor :Extractor[W, X]) :Extractor[W, Y] = extractor andThen this
Commenting out the andThen variant taking a function solves the issue.
So does changing the code to extractor.andThen[Y](this) (explicit type parameter is the key here).
My guess is that somehow my SAM type gets promoted to a function, but I can't guess why would it take precedence over a method. As I provided here two 'solutions', I am looking not as much for workarounds, but to understand what is happening. It's the first time in years I don't understand what's happening and would like to eliminate similar issues in the future.