强制隐式调用的依赖类型解析

2024-04-18

我有一个包装特征:


trait Wrapper[T] {

  ...
  type Own[F[_]] <: OwnThing[F]
  def ask[F[_]](implicit own: Own[F])

}

还有不同的实现,这里是一个例子:

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]) = ???
}

但隐式解析不会解析路径相关类型,因此找不到任何隐式。

有没有办法强制解析路径依赖类型? 就目前而言,我只是将它们视为变量,但处于类型级别。

编辑 : 更完整的版本:


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:一个不起作用的例子

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:对我来说,问题的根源在于CombinedWrapper在类型成员定义处。我认为 Scala 没有解决定义中路径依赖类型的使用。

我可以这么说是因为

new SimpleWrapper[String].ask

是否编译


首先修复几个错别字

//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] { ...

然后,调试隐式的标准方法是手动解决它们(可能显式指定一些类型参数)并查看编译错误。

new SimpleWrapper[String].ask
new SimpleWrapper[Int].ask

实际上是

new SimpleWrapper[String].ask[Id](stringOwn)
new SimpleWrapper[Int].ask[Id](intOwn)

如果你试试

combined.ask[Id](composeOwnIds(stringOwn, intOwn))

你会有

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]

如果你试试

combined.ask[Id](composeOwnIds[String, Int, SimpleOwn[Id, String], SimpleOwn[Id, Int]](stringOwn, intOwn))

你会有

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]]

如果你更换

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))

会给

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))

问题是虽然combined.wrapperA is strWrapper and combined.wrapperB is intWrapper但类型combined.wrapperA.Own[Id] and strWrapper.Own[Id]不同且类型不同combined.wrapperB.Own[Id] and intWrapper.Own[Id]也不同。

例如,如果您有

trait MyTrait { type T }
val mt = new MyTrait {}
val mt1 = mt

那么值相等但类型不同

//  implicitly[mt.T =:= mt1.T] // doesn't compile
//  implicitly[mt1.T =:= mt.T] // doesn't compile

尝试修改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

  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]) = ???
  }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

强制隐式调用的依赖类型解析 的相关文章

随机推荐

  • 如何检测当前作用域在 CMake 中是否有父作用域?

    有什么方法可以检测当前作用域是否有父作用域 我有一个项目 可以是独立项目 也可以是另一个项目的子项目 为了允许子项目情况 我使用 PARENT SCOPE 标志来 set 将内容推送到父项目 但是 当构建为独立项目时 我收到 当前范围没有父
  • IllegalArgumentException Base64到图像解码android

    我想将 Base64 格式的 Web 服务中的图像解码为位图 并在我的 Android 应用程序中使用它 这是我的方法 public Bitmap getCaptcha throws IOException List
  • (ngModelChange) 不会更新特定输入的 UI

    我有一个输入字段 用户可以在其中输入某物的比率 当用户输入一个值时 我希望在四舍五入后显示该值 然后将更新后的值存储在支持模型中ts file 使用 Angular 管道对此效果不佳 因为单向管道和更新的值不会反映在模型上 因此 为了使其双
  • 如何使用 image_picker 依赖项将图像上传到 flutter 中的 sqlite 数据库

    Future getImage ImageSource imageSource async var image await ImagePicker pickImage source imageSource setState image im
  • STL 中 next_permutation 的 Python 实现

    next permutation 是一个 C 函数 它给出字符串按字典顺序排列的下一个排列 有关其实现的详细信息可以从这篇非常棒的文章中获得 http wordaligned org articles next permutation ht
  • CXF ClientProxy getClient“不是代理实例”

    我正在尝试将 WS security 与我的 Apache CXF 客户端结合使用 我需要掌握客户端端点 以便添加 WSS4J 拦截器 然而 当我打电话时ClientProxy getClient 我得到一个IllegalArgumentE
  • 无法使用 Visual Studio 2013 社区运行 Xunit

    我正在尝试让 XUnit 与 Visual Studio 2013 Community 版本 12 0 31101 00 Update 4 一起使用 我已经让 NUnit 工作了 所以我认为让 XUnit 工作起来会很简单 代码是 usin
  • java.net.ConnectException:无法连接到/127.0.0.1:9080领域对象服务器

    我在看到网站中的文档后刚刚安装了领域对象服务器 我创建了一个登录页面 android 并根据网站使用了同步用户设置 但我在创建时的 asynctask 显示了上述错误 这是我的代码 public class RealAsyncTask ex
  • 动态创建类属性

    我正在寻找一种方法来动态创建具有可通过典型实例表示法访问的特定属性的类 DynoOne createClass DynoOne props A B d DynoOne database XYZ d A d B 1 DynoTwo creat
  • 有没有办法获得总设备内存?我需要它来优化

    我有一个可以包含静态数据的 lrucache 这样即使我的应用程序在用户返回时关闭 他也可以更快地找到数据 然而 这需要大约 10 15 MB 的内存 所以我想创建一个像这样的 if 分支 if deviceOverallRAM gt tr
  • 从一个活动调用另一个活动中的方法

    我知道我们无法从另一个活动中的活动调用方法 我正在尝试找出解决这个问题的最佳方法 这是我的代码 这是我试图调用的方法 它在我的ScoreCard活动 public void numPlayerSetup int ids R id TextV
  • 更改文件创建日期不起作用

    我使用以下命令来更改文本文件的创建日期 using System IO DateTime newCreate new DateTime year month day hour minutes seconds File SetCreation
  • 在 JavaScript 中确定域名?

    使用有什么区别 if document domain toLowerCase indexOf domainName 1 and if window location href match 1 toLowerCase indexOf doma
  • 是否可以使用 content:// 作为 WebView 中

    我创建了一个ContentProvider 它导出我的 asset 目录中的文件 我使用 content url 来访问 WebView 中导出的内容 以下 HTML 按预期工作 img src 我正在尝试使用 mp3 音频文件的内容提供程
  • php 将变量绑定到旧 PHP 中的函数作用域

    我想将变量绑定到函数的作用域 我可以在 PHP 5 3 之后使用 use 关键字在 php 中执行此操作 但是如何在 PHP 5 3 以下的版本中执行等效操作 test use keyword function test use keywo
  • RDBMS 对 Golang 的影响 [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我不会对这个关于我测试过的内容和数字运算的问题进行长篇大论 我对最新的实际练习表演更感兴趣 我已经阅读了大量的文章 其中一些非常怀疑 或者非常怀
  • Visual Studio 默认自动完成使用系统类型名称

    奇怪的问题 但我的老板有点老派 坚持在我们的编码标准中我们不使用 C 简写系统类型 他喜欢我们使用完整的系统名称 他喜欢事情变得冗长 我很乐意遵守这个标准 然而 几个月后开始让我恼火的是 Visual Studio 在完成代码时不喜欢遵守标
  • Android 如何从相机捕获两个连续的帧

    我正在尝试在 Android 设备上对光流进行编程 我的问题是从相机获取两个连续的帧 这是获取一帧的代码 mCamera setPreviewCallback new PreviewCallback public void onPrevie
  • Java 装饰器模式:我可以装饰受保护的方法吗?

    我想要Decorate 装饰器设计模式 一个通用的基类 但是我需要的方法Decorate受到保护 参见示例 public class AbstractActor public void act Delegates its actions t
  • 强制隐式调用的依赖类型解析

    我有一个包装特征 trait Wrapper T type Own F lt OwnThing F def ask F implicit own Own F 还有不同的实现 这里是一个例子 class CombinedWrapper A B