I am having difficulty resolving this type mismatch compilation error
I have a series of Sources that I want to implement the strategy pattern to process the appropriate type
sealed trait Source
case class SourceA extends Source
case class SourceB extends Source
My preprocessor consists of a number of strategies that will process the appropriate case class
trait SourceStrategy[T <: Source] {
def isApplicable(source: Source): Boolean
def preprocess(source: T): Whatever
}
The idea is that a SourceStrategy implementation will exist for each case class above
I want to do something like this, whereby I loop through the appropriate strategies, find the one that is applicable and then invoke that one
class MyPreprocessor (strategies: Set[SourceStrategy[_ <: Source]]) {
def performPreprocessing(source: Source) = {
val preprocessor = strategies.filter(b => b.isApplicable(source)).head
preprocessor.preprocess(source)
}
}
I am getting a mismatch between _$1
and Source
in this last line.
I understand the reason that this occurs but I'm just not sure how to resolve it in a clean manner
Either you want to check that a current strategy is applicable to a current source at compile time or you want to check this at runtime.
If you do at runtime then there is not much sense in making SourceStrategy
generic
trait SourceStrategy {
def isApplicable(source: Source): Boolean
def preprocess(source: Source): Whatever
}
class MyPreprocessor (strategies: Set[SourceStrategy]) {
def performPreprocessing(source: Source) = {
val preprocessor = strategies.filter(b => b.isApplicable(source)).head
preprocessor.preprocess(source)
}
}
If you do at compile time then you can use heterogeneous collection and type class
trait PerformPreprocessing[L <: HList, T <: Source] {
def performPreprocessing(strategies: L, source: T): Whatever
}
object PerformPreprocessing {
implicit def recur[T <: Source, S, L <: HList, T1 <: Source](implicit
performPreprocessing: PerformPreprocessing[L, T1]
): PerformPreprocessing[S :: L, T1] =
(strategies, source) => performPreprocessing.performPreprocessing(strategies.tail, source)
implicit def base[T <: Source, S <: SourceStrategy[T], L <: HList]: PerformPreprocessing[S :: L, T] =
(strategies, source) => strategies.head.preprocess(source)
}
class MyPreprocessor[L <: HList](strategies: L) {
def performPreprocessing[T <: Source](source: T)(implicit
performPreprocessing: PerformPreprocessing[L, T]
): Whatever =
performPreprocessing.performPreprocessing(strategies, source)
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.