[英]Force dependent types resolution for implicit calls
I have a wrapper trait : 我有一个包装特征:
trait Wrapper[T] {
...
type Own[F[_]] <: OwnThing[F]
def ask[F[_]](implicit own: Own[F])
}
And different implementations, here is an example : 不同的实现,这是一个例子:
class CombinedWrapper[A, B](wrapperA: Wrapper[A], wrapperB: Wrapper[B]) extends Wrapper[(A, B)] {
override type Own[F[_]] = SomeOwnThing[(A, B), wrapperA.Own[F], wrapperB.Own[F]]
override def ask[F[_]](implicit own: Own[F]) = ???
}
But the implicit resolution will not resolve the path-dependent types, therefore not finding any implicits. 但隐式解决方案不会解决路径依赖类型,因此找不到任何含义。
Is there a way to force the resolution of path-dependent types? 有没有办法强制解决路径依赖类型? As for now, I just think of them as variables but at the type level. 至于现在,我只是将它们视为变量而是在类型级别。
Edit : A more complete version: 编辑:更完整的版本:
trait Wrapper[T] {
...
type Own[F[_]] <: OwnThing[F, T]
def ask[F[_]](implicit own: Own[F])
}
sealed trait OwnThing[F[_], A]
trait SomeOwnThing[F[_], A, B, ThingA <: OwnThing[F, A], ThingB <: OwnThing[F, B]] extends OwnThing[F, (A, B)] {
def underlyingA: ThingA
def underlyingB: ThingB
}
class CombinedWrapper[A, B](wrapperA: Wrapper[A], wrapperB: Wrapper[B]) extends Wrapper[(A, B)] {
override type Own[F[_]] = SomeOwnThing[F, A, B, wrapperA.Own[F], wrapperB.Own[F]]
override def ask[F[_]](implicit own: Own[F]) = ???
}
Edit2: A non-working example Edit2:一个非工作的例子
trait SimpleOwn[F[_], A] extends OwnThing[F, A]
class SimpleWrapper[T] extends Wrapper[T] {
override type Own[F[_]] = SimpleOwn[F, T]
override def ask[F[_]](implicit own: Own[F]) = ???
}
val combined = new CombinedWrapper[String, Int](new SimpleWrapper[String], new SimpleWrapper[Int])
type Id[A] = A
//Simple case for base types
implicit val intOwn: SimpleOwn[Id, Int] = new SimpleOwn[Id, Int]
implicit val stringOwn: SimpleOwn[Id, String] = new SimpleOwn[Id, String]
//Should combine the two above
implicit def composeOwnIds[A, B, ThingA <: OwnThing[Id, A], ThingB <: OwnThing[Id, B]](implicit aOwn: ThingA, bOwn: ThingB): SomeOwnThing[Id, A, B, ThingA, ThingB] = new SomeOwnThing {
override def underlyingA: ThingA = aOwn
override def underlyingB: ThingB = bOwn
}
//Should work but cant find implicit
combined.ask[Id]
Edit3: For me, the root of the problem is in CombinedWrapper
at the type member definition. Edit3:对我来说,问题的根源在于类型成员定义的CombinedWrapper
。 I think Scala does not resolve the path-dependent-types use in the definition. 我认为Scala没有解决定义中依赖路径的类型。
I can say this because 我可以这么说因为
new SimpleWrapper[String].ask
does compile 编译
Firstly fix couple of typos 首先解决几个拼写错误
//class CombinedWrapper[A, B](wrapperA: Wrapper[A], wrapperB: Wrapper[B]) extends Wrapper[(A, B)] {
class CombinedWrapper[A, B](val wrapperA: Wrapper[A], val wrapperB: Wrapper[B]) extends Wrapper[(A, B)] { ...
//implicit val intOwn: SimpleOwn[Id, Int] = new SimpleOwn[Id, Int]
implicit val intOwn: SimpleOwn[Id, Int] = new SimpleOwn[Id, Int] {}
//implicit val stringOwn: SimpleOwn[Id, String] = new SimpleOwn[Id, String]
implicit val stringOwn: SimpleOwn[Id, String] = new SimpleOwn[Id, String] {}
//implicit def composeOwnIds[A, B, ThingA <: OwnThing[Id, A], ThingB <: OwnThing[Id, B]](implicit aOwn: ThingA, bOwn: ThingB): SomeOwnThing[Id, A, B, ThingA, ThingB] = new SomeOwnThing {
implicit def composeOwnIds[A, B, ThingA <: OwnThing[Id, A], ThingB <: OwnThing[Id, B]](implicit aOwn: ThingA, bOwn: ThingB): SomeOwnThing[Id, A, B, ThingA, ThingB] = new SomeOwnThing[Id, A, B, ThingA, ThingB] { ...
Then standard way to debug implicits is to resolve them manually (maybe specifying some type parameters explicitly) and see compile errors. 然后调试implicits的标准方法是手动解决它们(可能显式指定一些类型参数)并查看编译错误。
new SimpleWrapper[String].ask
new SimpleWrapper[Int].ask
are actually 实际上是
new SimpleWrapper[String].ask[Id](stringOwn)
new SimpleWrapper[Int].ask[Id](intOwn)
If you try 如果你试试
combined.ask[Id](composeOwnIds(stringOwn, intOwn))
you'll have 你会的
Error: type mismatch;
found : App.intOwn.type (with underlying type App.SimpleOwn[App.Id,Int])
required: App.combined.wrapperB.Own[App.Id]
Error: type mismatch;
found : App.stringOwn.type (with underlying type App.SimpleOwn[App.Id,String])
required: App.combined.wrapperA.Own[App.Id]
If you try 如果你试试
combined.ask[Id](composeOwnIds[String, Int, SimpleOwn[Id, String], SimpleOwn[Id, Int]](stringOwn, intOwn))
you'll have 你会的
Error: type mismatch;
found : App.SomeOwnThing[App.Id,String,Int,App.SimpleOwn[App.Id,String],App.SimpleOwn[App.Id,Int]]
required: App.combined.Own[App.Id]
(which expands to) App.SomeOwnThing[App.Id,String,Int,App.combined.wrapperA.Own[App.Id],App.combined.wrapperB.Own[App.Id]]
If you replace 如果你更换
val combined = new CombinedWrapper[String, Int](new SimpleWrapper[String], new SimpleWrapper[Int])
with 同
val strWrapper = new SimpleWrapper[String]
val intWrapper = new SimpleWrapper[Int]
val combined = new CombinedWrapper[String, Int](strWrapper, intWrapper)
then 然后
combined.ask[Id](composeOwnIds[String, Int, strWrapper.Own[Id], intWrapper.Own[Id]](stringOwn, intOwn))
will give 会给
Error: type mismatch;
found : App.SomeOwnThing[App.Id,String,Int,App.strWrapper.Own[App.Id],App.intWrapper.Own[App.Id]]
(which expands to) App.SomeOwnThing[App.Id,String,Int,App.SimpleOwn[App.Id,String],App.SimpleOwn[App.Id,Int]]
required: App.combined.Own[App.Id]
(which expands to) App.SomeOwnThing[App.Id,String,Int,App.combined.wrapperA.Own[App.Id],App.combined.wrapperB.Own[App.Id]]
combined.ask[Id](composeOwnIds[String, Int, strWrapper.Own[Id], intWrapper.Own[Id]](stringOwn, intOwn))
The thing is that although combined.wrapperA
is strWrapper
and combined.wrapperB
is intWrapper
but types combined.wrapperA.Own[Id]
and strWrapper.Own[Id]
are different and types combined.wrapperB.Own[Id]
and intWrapper.Own[Id]
are different too. 问题是虽然combined.wrapperA
是strWrapper
和combined.wrapperB
是intWrapper
但类型combined.wrapperA.Own[Id]
和strWrapper.Own[Id]
是不同的类型combined.wrapperB.Own[Id]
和intWrapper.Own[Id]
也不同。
For example if you have 例如,如果你有
trait MyTrait { type T }
val mt = new MyTrait {}
val mt1 = mt
then values are equal but types are different 然后价值相等但类型不同
// implicitly[mt.T =:= mt1.T] // doesn't compile
// implicitly[mt1.T =:= mt.T] // doesn't compile
Try to modify CombinedWrapper
adding more type parameters and specify them with specific dependent types at call site 尝试修改CombinedWrapper
添加更多类型参数,并在调用站点使用特定的依赖类型指定它们
trait Wrapper[T] {
type Own[F[_]] <: OwnThing[F, T]
def ask[F[_]](implicit own: Own[F])
}
sealed trait OwnThing[F[_], A]
trait SomeOwnThing[F[_], A, B, ThingA <: OwnThing[F, A], ThingB <: OwnThing[F, B]] extends OwnThing[F, (A, B)] {
def underlyingA: ThingA
def underlyingB: ThingB
}
// class CombinedWrapper[A, B](val wrapperA: Wrapper[A], val wrapperB: Wrapper[B]) extends Wrapper[(A, B)] {
// override type Own[F[_]] = SomeOwnThing[F, A, B, wrapperA.Own[F], wrapperB.Own[F]]
// override def ask[F[_]](implicit own: Own[F]) = ???
// }
class CombinedWrapper[A, B, OwnA[F[_]] <: OwnThing[F, A], OwnB[F[_]] <: OwnThing[F, B]](
val wrapperA: Wrapper[A] { type Own[F[_]] = OwnA[F] },
val wrapperB: Wrapper[B] { type Own[F[_]] = OwnB[F] }
) extends Wrapper[(A, B)] {
override type Own[F[_]] = SomeOwnThing[F, A, B, OwnA[F], OwnB[F]]
override def ask[F[_]](implicit own: Own[F]) = ???
}
trait SimpleOwn[F[_], A] extends OwnThing[F, A]
class SimpleWrapper[T] extends Wrapper[T] {
override type Own[F[_]] = SimpleOwn[F, T]
override def ask[F[_]](implicit own: Own[F]) = ???
}
// val combined = new CombinedWrapper[String, Int](new SimpleWrapper[String], new SimpleWrapper[Int])
val strWrapper = new SimpleWrapper[String]
val intWrapper = new SimpleWrapper[Int]
val combined = new CombinedWrapper[String, Int, strWrapper.Own, intWrapper.Own](strWrapper, intWrapper)
type Id[A] = A
implicit val intOwn: SimpleOwn[Id, Int] = new SimpleOwn[Id, Int] {}
implicit val stringOwn: SimpleOwn[Id, String] = new SimpleOwn[Id, String] {}
implicit def composeOwnIds[A, B, ThingA <: OwnThing[Id, A], ThingB <: OwnThing[Id, B]](implicit aOwn: ThingA, bOwn: ThingB): SomeOwnThing[Id, A, B, ThingA, ThingB] = new SomeOwnThing[Id, A, B, ThingA, ThingB] {
override def underlyingA: ThingA = aOwn
override def underlyingB: ThingB = bOwn
}
combined.ask[Id] // compiles
new SimpleWrapper[String].ask // compiles
Using Aux
type 使用Aux
类型
trait Wrapper[T] {
type Own[F[_]] <: OwnThing[F, T]
def ask[F[_]](implicit own: Own[F])
}
object Wrapper {
type Aux[T, Own0[F[_]] <: OwnThing[F, T]] = Wrapper[T] { type Own[F[_]] = Own0[F] }
}
class CombinedWrapper[A, B, OwnA[F[_]] <: OwnThing[F, A], OwnB[F[_]] <: OwnThing[F, B]](
val wrapperA: Wrapper.Aux[A, OwnA], val wrapperB: Wrapper.Aux[B, OwnB]
) extends Wrapper[(A, B)] {
override type Own[F[_]] = SomeOwnThing[F, A, B, OwnA[F], OwnB[F]]
override def ask[F[_]](implicit own: Own[F]) = ???
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.