The trait just makes the ambiguous fan-out easier to pull off. Returning Curried
would probably have worked as well.
If I’m understanding things correctly, if you convert Calculate("const", 1, 2)
, you’ll get this:
/* 0 */ Calculate
/* 1 */ .applyBegin
/* 2 */ .applyNext("const")
/* 3 */ .applyNext(1)
/* 4 */ .applyNext(2)
/* 5 */ .applyEnd
Until line 2, the compiler knows the exact type which will be returned, but from line 2 on, the return value is just Operation
, which extends Curried
.
On line 3, either the compiler looks and sees that Operation
doesn’t implement these directly, and fails to compile, or trusts that one of it’s subtypes will implement it (though it doesn’t know which one) and the code triggers a NoSuchMethodError
at runtime.
So, I guess the problem isn’t that Operation
extends Curried
, it’s that the return type is dependent on the value passed. Overloading applyNext
should work, because the compiler can trace the types, but I don’t know if there’s a way to do this for runtime values (or a good way to prevent this from happening).