依赖方法类型有哪些引人注目的用例?

2023-12-10

依赖方法类型以前是一个实验性功能,现在已经成为中继中默认启用,显然这似乎创造了一些兴奋在 Scala 社区中。

乍一看,这有什么用处并不是很明显。 Heiko Seeberger 发布了一个依赖方法类型的简单示例here,正如在评论中可以看到的那样,可以使用方法上的类型参数轻松地重现它。所以这不是一个非常有说服力的例子。 (我可能遗漏了一些明显的东西。如果是这样,请纠正我。)

依赖方法类型的用例有哪些实际且有用的示例,它们明显优于替代方法?

我们可以用它们做哪些以前不可能/容易的有趣的事情?

与现有的类型系统功能相比,他们给我们带来了什么?

另外,依赖方法类型是否与其他高级类型语言(例如 Haskell、OCaml)的类型系统中发现的任何功能类似或从中汲取灵感?


成员(即嵌套)类型的任何使用或多或少都会引起对依赖方法类型的需求。特别是,我认为如果没有依赖的方法类型,经典的蛋糕模式更接近于反模式。

所以有什么问题? Scala 中的嵌套类型取决于它们的封闭实例。因此,在缺乏依赖方法类型的情况下,尝试在该实例之外使用它们可能会非常困难。这可能会将最初看起来优雅且有吸引力的设计变成可怕的僵化且难以重构的怪物。

我将通过我在学习期间进行的练习来说明这一点Scala 高级培训课程,

trait ResourceManager {
  type Resource <: BasicResource
  trait BasicResource {
    def hash : String
    def duplicates(r : Resource) : Boolean
  }
  def create : Resource

  // Test methods: exercise is to move them outside ResourceManager
  def testHash(r : Resource) = assert(r.hash == "9e47088d")  
  def testDuplicates(r : Resource) = assert(r.duplicates(r))
}

trait FileManager extends ResourceManager {
  type Resource <: File
  trait File extends BasicResource {
    def local : Boolean
  }
  override def create : Resource
}

class NetworkFileManager extends FileManager {
  type Resource = RemoteFile
  class RemoteFile extends File {
    def local = false
    def hash = "9e47088d"
    def duplicates(r : Resource) = (local == r.local) && (hash == r.hash)
  }
  override def create : Resource = new RemoteFile
}

这是经典蛋糕模式的一个例子:我们有一个抽象家族,它们通过层次结构逐渐完善(ResourceManager/Resource被精炼为FileManager/File又经过精炼NetworkFileManager/RemoteFile)。这是一个玩具示例,但该模式是真实的:它在整个 Scala 编译器中使用,并在 Scala Eclipse 插件中广泛使用。

这是使用抽象的示例,

val nfm = new NetworkFileManager
val rf : nfm.Resource = nfm.create
nfm.testHash(rf)
nfm.testDuplicates(rf)

请注意,路径依赖意味着编译器将保证testHash and testDuplicates上的方法NetworkFileManager只能使用与其相对应的参数来调用。它自己的RemoteFiles,没有别的。

无可否认,这是一个理想的属性,但假设我们想将此测试代码移动到不同的源文件中?使用依赖方法类型,在外部重新定义这些方法非常容易ResourceManager等级制度,

def testHash4(rm : ResourceManager)(r : rm.Resource) = 
  assert(r.hash == "9e47088d")

def testDuplicates4(rm : ResourceManager)(r : rm.Resource) = 
  assert(r.duplicates(r))

请注意此处依赖方法类型的使用:第二个参数的类型 (rm.Resource) 取决于第一个参数的值 (rm).

在没有依赖方法类型的情况下可以做到这一点,但它非常尴尬,而且机制也很不直观:我已经教授这门课程近两年了,在那段时间里,没有人能自发地提出一个可行的解决方案。

自己尝试一下...

// Reimplement the testHash and testDuplicates methods outside
// the ResourceManager hierarchy without using dependent method types
def testHash        // TODO ... 
def testDuplicates  // TODO ...

testHash(rf)
testDuplicates(rf)

经过一段时间的挣扎后,你可能会发现为什么我(或者也许是大卫·麦基弗,我们不记得我们中谁创造了这个词)将其称为“末日面包店”。

Edit:共识是《末日面包店》是大卫·麦基弗的创造物……

额外的好处是:Scala 的依赖类型形式(以及依赖方法类型作为其中的一部分)受到编程语言的启发Beta...它们自然地源于 Beta 一致的嵌套语义。我不知道有任何其他甚至微弱的主流编程语言具有这种形式的依赖类型。 Coq、Cayenne、Epigram 和 Agda 等语言具有不同形式的依赖类型,这种类型在某些方面更为通用,但由于属于类型系统的一部分而存在显着差异,与 Scala 不同,类型系统没有子类型。

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

依赖方法类型有哪些引人注目的用例? 的相关文章

随机推荐

  • 重定向后进入 asp.net

    我有兴趣在我的网站中为我创建的某些表单实施 PRG 目前 他们回发给自己 并且显然刷新这些页面会重复发布数据 谁能给我指点一个很好的教程 告诉我如何将其编码到我的网站中 我理解逻辑 但不确定从哪里开始 谢谢 回发到表单后 您只需在回发后执行
  • dequeueReusableCellWithIdentifier 总是返回非零?

    在下面返回的经典图案中cell from dequeueReusableCellWithIdentifier总是非nil 为什么 难道我们不应该先分配一些单元格 然后我们才能重用一些单元格吗 我正在使用自定义单元格 它是在故事板中创建的 但
  • mysqli_connect(): (HY000/2002): 无法通过套接字连接到本地 MySQL 服务器

    我需要帮助 我尝试使用 php 显示数据库时遇到此错误 mysqli connect HY000 2002 无法连接到本地 MySQL 服务器 通过套接字 Applications MAMP tmp mysql mysql sock 2 中
  • C#:创建一个可以将枚举返回为 List 的通用方法

    我怎样才能创建一个generic接收枚举类型并将其值和名称作为字符串列表返回的方法 因此我可以循环此列表 并且对于每次迭代 我将能够打印每个枚举值 例如 考虑下一个伪 enum MyEnum A 5 B 6 C 8 List
  • 为来自 appengine 的 freebase 查询设置 api 密钥

    我已遵循以下说明 https developers google com console help generatedevkeys 我注册了 freebase 服务 并将浏览器应用程序的简单 API 密钥添加到查询中 MQL查询 然后我收到
  • ElasticSearch 返回错误距离 distanceInKm

    我已经实现了一个返回距离的脚本字段 如下所示在elasticsearch结果中返回距离 Ruby script fields distance script doc source field distanceInKm lat lng 但是返
  • 使用 Application 类作为全局变量

    有什么理由不使用 Application 类在 Activity 之间共享变量吗 例如数据库句柄或单个 HttpClient 根据官方文档 您可以使用它来维护全局应用程序状态 在我看来 全球范围内你都不想抓住太多重物 当然 太多 太模糊了
  • 为什么在用作函数参数之前需要将子类型分配给变量?

    我正在学习子类型 并且想知道为什么这里给出一个例子https www typescriptlang org docs handbook type compatibility html可以编译 但是当我将子类型直接作为参数传递给函数时 它不会
  • 确定 `set -e` 标志在 bash 中是否处于活动状态

    在 bash 脚本 shell 中 是否有一种编程方式来确定是否set e标志处于活动状态吗 我只需要一个布尔值让我知道它是否打开 关闭 From help test o OPTION True if the shell option OP
  • PowerShell 2 中是否有一个 cmdlet 可以处理 ipsec 更改?

    我正在使用 System Management Automation 构建一个本质上充当防火墙的程序 我想知道 PowerShell 2 中是否有特定的 cmdlet 来处理服务器的 ipsec 更改 即 重复 netsh ipsec 功能
  • 数据以 64512 个字符结束 - MSSQL // PHP // OPENSuSE // APACHE2

    我正在通过 PHP 使用适用于 Linux 的 FREETDS 驱动程序连接到 Windows Server 上的 mssql 数据库 运行应用程序的 Web 服务器运行 OPENSuSE 带有 PHP 的 Apache2 FreeTDS
  • Bash:如何选择数组中的元素

    我有一个包含子目录和文件的数组 array elem1 a elem1 b elem2 a elem2 b 我需要选择子目录中的所有文件 及其子目录 elem1 我尝试过for循环和case for element in array do
  • page.set('content') 不适用于 phantomjs 中的动态内容

    我尝试使用 phantomjs 来屏幕捕获我的页面节点幻象桥 这是我正在尝试的 var phantom require node phantom phantom create function err ph return ph create
  • java中如何获得大于整数空间的列表

    我在java中使用java util List来存储我的计算结果 如何存储大于最大整数的索引值 例如大 简而言之 您将不会使用 java util List 接口 你将不得不实施其他事情 如果这是我的程序 并且不是为某些特定的超级计算环境量
  • Java 8 Stream flatMap 和 group by 代码编译器错误

    given a set of Item objects group them by the managers of creator and owners Map
  • 使用 mongooseexpress 更新哈希密码

    我回顾了关于这个问题的许多讨论 但似乎没有一个对我有帮助 我使用 mongoose 5 5 来保存用户数据 如下所示 我的架构如下所示 const mongoose require mongoose const Schema mongoos
  • WMI 进程监视使用过多的 CPU!还有更好的方法吗?

    我需要观察 Windows 计算机上某些进程何时启动或停止 我目前正在使用 WMI 系统并每 5 秒查询一次 但这会导致每 5 秒出现一次 CPU 峰值 因为 WMI 是 WMI 有更好的方法吗 我可以只列出正在运行的进程 并通过 Syst
  • 限制批处理作业的生命周期

    有没有办法将正在运行的 Spring Batch 作业的生命周期限制为例如23小时 我们每天通过 cron 作业启动批处理作业 该作业大约需要 9 个小时 在某些情况下 数据库连接速度太慢 导致作业需要 60 多个小时才能完成 问题是下一个
  • 获取每个子数组每列的数组和

    这是我的数组 array HRI gt 14157 72 39140 94 36383 66 38508 8424 14157 72 39140 94 36383 66 38508 8424 14157 72 39140 94 36383
  • 依赖方法类型有哪些引人注目的用例?

    依赖方法类型以前是一个实验性功能 现在已经成为中继中默认启用 显然这似乎创造了一些兴奋在 Scala 社区中 乍一看 这有什么用处并不是很明显 Heiko Seeberger 发布了一个依赖方法类型的简单示例here 正如在评论中可以看到的