To better explain the title, I am selecting one of several functions to accumulate log data. The selection of the function is done via a parameter (color).
enum TraceColor derives CanEqual:
case BlackAndWhite, Colours, Gray
The selected “add-trace” functions take in an accumulator (String) and a result:
sealed trait QAResult[R]:
def report: String
Here are the trace functions:
def addTrace[R](trace: String, result: QAResult[R]): String = ???
def addColouredTrace[R](trace: String, result: QAResult[R]): String = ???
def addGrayTrace[R](trace: String, result: QAResult[R]): String = ???
which are invoked in a fold
function:
def fold[I](
r: I,
add: (String, QAResult[_]) => String
): String =
???
And here is one way to select a trace function that works:
def trace[I](r: I, colour: TraceColor = TraceColor.BlackAndWhite): String =
import TraceColor._
colour match
case BlackAndWhite => fold(r, addTrace)
case Colours => fold(r, addColouredTrace)
case Gray => fold(r, addGrayTrace)
If however I assign the trace function to a value:
def traceBad_1[I](r: I, colour: TraceColor = TraceColor.BlackAndWhite): String =
import TraceColor._
val func =
colour match
case BlackAndWhite => addTrace
case Colours => addColouredTrace
case Gray => addGrayTrace
fold(r, func)
I get the error:
Found: (func : (String, Playground.QAResult[Any]) => String)
Required: (String, Playground.QAResult[?]) => String
If I add another type parameter R
and assign that explicit to the fold, it works:
def fold0[I,R](
r: I,
add: (String, QAResult[R]) => String
): String =
???
def traceBad_3[I,R](r: I, colour: TraceColor = TraceColor.BlackAndWhite): String =
import TraceColor._
addTrace[R]
val func = if colour == BlackAndWhite then addTrace[R]
else if colour == Colours then addColouredTrace[R]
else addGrayTrace[R]
fold0[I,R](r, func)
So my question is, shouldn’t the first case fail to compile? If not, why?
The code can be found in scastie
TIA