Implicit conversions not working with type parameters
-
28-05-2021 - |
Вопрос
I am having an issue with implicit conversions not working under certain circumstances (higher kinded types). Given a system, an expression type, and two specific expression sub types:
trait Sys[S <: Sys[S]]
object Expr {
trait Var [S <: Sys[S], A] extends Expr[S, A]
trait Const[S <: Sys[S], A] extends Expr[S, A]
}
trait Expr[S <: Sys[S], A]
And a pimp class for expression operations:
class RichDoubleExpr[S <: Sys[S]](ex: Expr[S, Double]) {
def gugu(): String = "yes"
}
Then let there be implicit conversions from primitives to expressions, and from expressions to expression ops:
implicit def const[S <: Sys[S]](d: Double): Expr[S, Double] =
new Expr.Const[S, Double] {}
implicit def exprOps[S <: Sys[S], A <% Expr[S, Double]](v: A): RichDoubleExpr[S] =
new RichDoubleExpr( v )
The following works (thus implicit method const
):
3.4.gugu()
The following does not work (thus implicit method exprOps
):
def test[S <: Sys[S]]: String = {
val v = new Expr.Var[S, Double] {}
v.gugu()
}
with the following error:
error: No implicit view available from java.lang.Object with
Expr.Var[S,Double] => Expr[S,Double].
v.gugu()
^
Now, since Expr.Var
extends Expr
and the type parameters are identical, that error message clearly doesn't make sense to me. Any ideas how to fix this?
Решение
A viable solution in my case is to somewhat 'fix' type parameter S
:
class ExprImplicits[S <: Sys[S]] {
implicit def const(d: Double): Expr[S, Double] = new Expr.Const[S, Double] {}
implicit def exprOps[A <% Expr[S, Double]](v: A): RichDoubleExpr[S] =
new RichDoubleExpr(v)
}
Now I can import the implicits for a particular system:
def test[S <: Sys[S]]: String = {
val imp = new ExprImplicits[S]
import imp._
3.4.gugu() // ok
val v = new Expr.Var[S, Double] {}
v.gugu() // ok
}