无形:Generic.Aux

2024-03-08

我试图理解如何Generic作品(和TypeClass也)。 github wiki 上的示例和文档非常稀疏。是否有规范的博客文章/文档页面描述Generic and TypeClass详细地?

具体来说,这两种方法有什么区别:

def find1[T](implicit gen: Generic[T]): Generic[T] = gen
def find2[T](implicit gen: Generic[T]): Generic[T] { type Repr = gen.Repr } = gen

given

object Generic {
  type Aux[T, Repr0] = Generic[T] { type Repr = Repr0 }
  def apply[T](implicit gen: Generic[T]): Aux[T, gen.Repr] = gen
  implicit def materialize[T, R]: Aux[T, R] = macro GenericMacros.materialize[T, R]
}

涉及的问题如何Generic and TypeClass已实现,并且它们所做的事情足够不同,因此它们可能值得单独提出问题,所以我会坚持Generic here.

Generic提供从案例类(以及可能相似的类型)到异构列表的映射。任何案例类都有一个唯一的 hlist 表示,但任何给定的 hlist 都对应于非常非常大量的潜在案例类。例如,如果我们有以下案例类:

case class Foo(i: Int, s: String)
case class Bar(x: Int, y: String)

hlist 表示由Generic对彼此而言Foo and Bar is Int :: String :: HNil,这也是表示(Int, String)以及我们可以按此顺序使用这两种类型定义的任何其他案例类。

(作为旁注,LabelledGeneric让我们能够区分Foo and Bar,因为它在表示形式中包含成员名称作为类型级字符串。)

我们通常希望能够指定案例类并让 Shapeless 找出(唯一的)通用表示,并使得Repr类型成员(而不是类型参数)允许我们非常干净地完成此操作。如果 hlist 表示类型是类型参数,那么您的find方法必须有一个Reprtype 参数,这意味着您不能仅指定T并拥有Repr推断。

Making Repr类型成员才有意义,因为Repr由第一个类型参数唯一确定。想象一下像这样的类型类Iso[A, B]见证那件事A and B是同构的。这个类型类非常类似于Generic, but A并不是唯一的真皮B——我们不能只问“什么是the同构于的类型A?”——所以它没有用B类型成员(尽管如果我们真的想的话我们可以——Iso[A]只是真的没有任何意义)。

类型成员的问题在于它们很容易被忘记,而且一旦消失,它们就永远消失了。事实上,你的返回类型find1未精炼(即不包括类型成员)意味着Generic它返回的实例几乎没有用。例如,静态类型res0这里也可能是Any:

scala> import shapeless._
import shapeless._

scala> def find1[T](implicit gen: Generic[T]): Generic[T] = gen
find1: [T](implicit gen: shapeless.Generic[T])shapeless.Generic[T]

scala> case class Foo(i: Int, s: String)
defined class Foo

scala> find1[Foo].to(Foo(1, "ABC"))
res0: shapeless.Generic[Foo]#Repr = 1 :: ABC :: HNil

scala> res0.head
<console>:15: error: value head is not a member of shapeless.Generic[Foo]#Repr
              res0.head
                   ^

当无形的Generic.materialize宏创建Generic[Foo]我们要求的实例,它是静态类型的Generic[Foo] { type Repr = Int :: String :: HNil }, 所以gen编译器传递给的参数find1拥有我们需要的所有静态信息。问题是我们然后显式将该类型向上转换为普通的旧的未精炼的类型Generic[Foo],从那时起编译器就不知道什么了Repr就是针对这种情况。

Scala 的路径依赖类型为我们提供了一种不忘记细化的方法without向我们的方法添加另一个类型参数。在你的find2,编译器静态地知道Repr对于传入的gen,所以当你说返回类型是Generic[T] { type Repr = gen.Repr },它将能够跟踪该信息:

scala> find2[Foo].to(Foo(1, "ABC"))
res2: shapeless.::[Int,shapeless.::[String,shapeless.HNil]] = 1 :: ABC :: HNil

scala> res2.head
res3: Int = 1

总结:Generic有一个类型参数T唯一确定其类型成员Repr, Repr是类型成员而不是类型参数,因此我们不必将其包含在所有类型签名中,并且路径相关类型使这成为可能,使我们能够跟踪Repr即使它不在我们的类型签名中。

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

无形:Generic.Aux 的相关文章

随机推荐

  • Git 将“未更改”的文件添加到舞台

    对于我正在从事的项目 我想使用 git add A 将一些文件添加到舞台上 问题是 Git 认为这些文件自上次提交以来没有变化 因此它们被忽略 然而 我亲自更改了该文件 但 Git 仍然认为该文件未更改 如何 强制 将该单个文件添加到我的存
  • 使用另一个表的总和更新表中的列

    我对 SQL 比较陌生 无法解决以下问题 简而言之 我有两张桌子 我们可以调用第一个表people name Margaret Jim Lola 第二个是一个列表expenses与不同实体相关的不同类型 name type amount M
  • 插入时数据类型不匹配(代码 20)

    在我的项目中 我使用 sqlite 数据库来保存图片及其位置 我在尝试将数据插入数据库时 收到此错误 E SQLiteLog 20 statement aborts at 5 INSERT INTO PHOTO VALUES NULL da
  • 如何在emr上重启hadoop集群

    我在 Amazon Elastic MapReduce 上安装了 hadoop 每当我尝试重新启动集群时 都会收到以下错误 stop all sh no jobtracker to stop The authenticity of host
  • React-Native是单线程执行还是多线程执行?

    我想通过示例了解 React Native 是否支持单线程或多线程方法 它是单线程的 请参考此链接 我想这会消除你所有的疑虑 https react native canny io feature requests p parallel m
  • 切换 Git 分支而不检出文件

    Git 是否可以在不检查所有文件的情况下切换到另一个分支 切换分支后 我需要删除所有文件 重新生成它们 提交并切换回来 所以检查文件只是浪费时间 大约有 14 000 个文件 这是一个很长的操作 为了让一切都清楚 我需要上传所有这些文档 h
  • Azure B2C Graph API - 强制用户在下次登录时更改密码[重复]

    这个问题在这里已经有答案了 我希望使用 graph api 来强制用户在下次登录时重置他 她的密码 如果我发送用户对象 ID 以及 forceChangePasswordNextLogin true我得到了成功的回复 但是 用户的帐户实际上
  • 如何在html5中浮动部分标签

    这可能是一个非常简单的问题 因此 如何漂浮 离开 section 标签 我尝试使用float left 但不起作用或者是否可以将标签与其内容垂直对齐 这是我的尝试 html div section h1 heyo h1 a href dro
  • as3 中的阿拉伯语文本

    如何使用as3从右到左显示阿拉伯文本 这段代码可以解决这个问题 import flash text AntiAliasType import flash text TextField import flash text TextFieldA
  • 总是在 Apache 中发送内容长度?

    我正在加载一个由 PHP 动态生成的特别大的 JSON 字符串 为了向用户提供一些反馈 我想显示下载进度 我已经弄清楚了代码 它对于静态内容 例如图像 JS 文件等 工作得很好 但是 它似乎不适用于动态文件 这是有道理的 因为动态文件没有可
  • 将 C# 委托转换为 f#

    如何将委托转换为 F 代表 delegate IntPtr HookProc int code IntPtr wParam IntPtr lParam Edited 我正在做的是使用 F 中的 C 托管 API 进行低级键盘挂钩 Code
  • 为什么 Spring Rest 服务在第一次请求时速度很慢?

    所以这个问题已经被问过几次了 但似乎没有人以可以帮助我的方式回答它 我目前正在为处理产品数据的简单应用程序制作后端 它甚至没有使用 JSP 只是一个普通的 Rest 后端 使用 Spring 的 RestController 问题 是 启动
  • 为什么在 C# 中经常看到“null!=variable”而不是“variable!=null”?

    在c 中 声明条件的顺序执行速度有什么区别吗 if null variable if variable null 最近以来 我经常看到第一个 因为我已经习惯了第二个 所以它引起了我的注意 如果没有区别 第一个的优点是什么 这是 C 语言的保
  • 蟒蛇龟太空入侵者的子弹没有击中入侵者

    一般来说 我对海龟和Python都很陌生 所以如果我的代码看起来很混乱 我深表歉意 我目前正在编写海龟版本的太空入侵者 我不明白为什么我的入侵者在击中海龟时没有死亡 该代码似乎与我能找到的所有其他太空入侵者海龟程序相同 任何帮助将不胜感激
  • 从支持 bean 重新加载页面

    在我的代码中 我正在扩展左框架中的树节点 该树节点是通过右框架中存在的导航链接选择的 它有效 但每次我单击右框架上的链接时 我都必须手动刷新右框架 我尝试使用 javascript 代码从支持 bean 重新加载页面 但它不起作用 谁能帮我
  • Matlab中的annotation()和text()

    我想知道有什么区别annotation and text Matlab 中的函数 在什么情况下 其中一个比另一个更受青睐 TEXT http www mathworks com access helpdesk help techdoc re
  • 如何将 git 存储库提交到 git 存储库(不是子模块)

    当我尝试将 git 存储库添加并提交到另一个 git 存储库时 git 会帮助将其放入子模块中 如果我want跟踪并提交对外部存储库中的嵌套存储库的更改 IE 我希望外部存储库跟踪嵌套存储库工作树及其 git 目录中的所有文件 这里的用例是
  • 在 bash 脚本中运行 ssh-agent

    我创建了文件 ssh start sh 其中包含 eval ssh agent s ssh add ssh id rsa 我正在运行它并有输出 Agent pid 1234 Identity added ssh id rsa ssh id
  • 在故事板中制作的容器视图不会以编程方式更改框架

    我有一个容器视图 property weak nonatomic IBOutlet UIView containerView 但是当我设置它的框架时它不会移动 这是我正在尝试的方法 void setFramesForCategories C
  • 无形:Generic.Aux

    我试图理解如何Generic作品 和TypeClass也 github wiki 上的示例和文档非常稀疏 是否有规范的博客文章 文档页面描述Generic and TypeClass详细地 具体来说 这两种方法有什么区别 def find1