Recursive Type Signatures in Scala

关于 JSNI 调用 Java 方法时的 Type Signatures 说明 关于 JSNI 调用 Java 方法时的 Type Signatures 说明. 立即下载

Have you seen a type signature like this before?

1
trait T[U <: T[U]]

If you’re like me, you’ve come across this type signature, and you’re wondering what the heck it means. You likely Googled something like “recursive type” or “self-referential type” and ended up here.

So what does this type signature mean? Why not use trait T[U]?

To understand the meaning of T[U <: T[U]], we’ll work through a simple example.

Example

Suppose we want database entities with CRUD methods. We could define them like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// I don't know about you, but I like to name my fruit.
case class Apple(name: String, price: Double) {
  def create(entityData: String): Apple
  def read(id: String): Option[Apple]
  def update(f: Apple => Apple): Apple
  def delete(id: String): Unit
}

case class Bird(name: String, birthday: DateTime) {
  def create(entityData: String): Bird
  def read(id: String): Option[Bird]
  def update(f: Bird => Bird): Bird
  def delete(id: String): Unit
}

But we can see that these classes look nearly identical. In addition, any new CRUD entities we add will expose the same CRUD methods. Now, should we abstract the interface into a trait? Let’s see what happens when we do:

1
2
3
4
5
6
7
8
9
10
trait CrudEntity {
  def create(entityData: String): CrudEntity
  def read(id: String): Option[CrudEntity]
  def update(f: CrudEntity => CrudEntity): CrudEntity
  def delete(id: String): Unit
}

case class Apple(name: String, age: Int) extends CrudEntity

case class Bird(name: String, hobby: String) extends CrudEntity

Well this sucks. Our method signatures don’t fully express what we want. We’ve lost the ability to ensure that e.g. calling update on an Apple returns an Apple. As is, it can return any CrudEntity. Let’s try to regain some specificity by adding a type parameter to our CrudEntitytrait:

1
2
3
4
5
6
7
8
9
10
trait CrudEntity_2[E] {
  def create(entityData: String): E
  def read(id: String): Option[E]
  def update(f: E => E): E
  def delete(id: String): Unit
}

case class Apple(name: String, age: Int) extends CrudEntity_2[Apple]

case class Bird(name: String, hobby: String) extends CrudEntity_2[Bird]

Okay, better. But we still haven’t locked this down. Our types don’t yet express exactly what we want. Do you see the problem?

The problem is that someone can extend CrudEntity_2 in a way we didn’t intend them to:

1
case class Orange(name: String, bankAccount: Double) extends CrudEntity_2[FloobyDust]

Whoa! In the code above, CrudEntity_2[E] does not restrict the type of E, so they can use anything they want, without complaint from the compiler — FloobyDust, Potato, BurritoAstronaut, you name it.

This is no bueno. Instead, we’d like them to get a big, fat compiler error if they try extending anything other than CrudEntity_2[Orange]. How do we ensure that E matches the class we’re defining?

Let’s try defining CrudEntity again. This time, we’ll use type bounds:

1
2
3
4
5
6
7
8
9
10
trait CrudEntity_3[E <: CrudEntity_3[E]] {
  def create(entityData: String): E
  def read(id: String): Option[E]
  def update(f: E => E): E
  def delete(id: String): Unit
}

case class Apple(name: String, age: Int) extends CrudEntity_3[Apple]

case class Bird(name: String, hobby: String) extends CrudEntity_3[Bird]

Better. Now we’ve constrained E to be a subtype of CrudEntity. No more FloobyDust. But there’s one last problem, and you can probably guess what it is. We haven’t yet ensured that E matches our class type, only that it subclasses CrudEntity. CrudEntity is still open for abuse:

1
case class Orange(name: String, age: Int) extends CrudEntity_3[Apple]

Yuck! To take care of this, we need a way to ensure that e.g. Orange extends CrudEntity_3[Orange]. For this assurance, we’ll use a self type.

Here is our final definition of CrudEntity, which uses a self type:

1
2
3
4
5
6
trait CrudEntity[E <: CrudEntity[E]] { self: E =>
  def create(entityData: String): E
  def read(id: String): Option[E]
  def update(f: E => E): E
  def delete(id: String): Unit
}

self: E => ensures that any concrete class that extends CrudEntity must be of type E and that code like

1
case class Orange(name: String, age: Int) extends CrudEntity[Apple]

will get rejected by the compiler because Orange is not of type Apple.

Now we can rest, confident that our definition of CrudEntity ensures that any subtype of CrudEntity[E] must in fact be an E. This definition gives us the semantics we desire, and enlists the compiler to reject all code in violation.

http://blog.originate.com/blog/2014/02/27/types-inside-types-in-scala/ 

用angr找到strcpy的栈溢出漏洞 这篇文章其实是分析angr文档里给出的一个挖漏洞的小例子。 原文链接在此:https://docs.angr.io/examples#beginner-vulnerability-discovery-example-strcpy_find 这是第一个用angr在二进制里找可利用条件的教程。第一个例子是一个非常简单的程序。这个angr脚本会从程序的entry到strcpy找到一条路径。(只有我们能够控制strcpy的参数的时候) 为了找到正确的路径,angr需要去算一个密码参数,算这个密码,angr只要2s 阅读详情

相关推荐

(SCADA)监控与数据采集系统

SCADA应用于监控和采集数据来控制工业过程软件。它通过收集和传输实时数据,帮助操作员监视和控制各种设备和过程。

软件技术的专栏 4542

19.智能指针

智能指针

SQZXR的博客 663

硬件开发实践:高速 PCB 差分信号与时钟同步优化

由两条互补信号线组成(正负极)接收端只关注两线之间电压差共模噪声对两线同时作用,可被抵消。

2501_93174775的博客 392

Java JNI 使用笔记

JNI 的全称是 Java Native Interface,是一种 Java 的 Native 编程接口,支持 Java 与 C/C++ 直接相互调用,从 JDK 1.0 开始提供。

mfmfmfo的博客 606

一分钟理解 AP(Affinity Propagation) 亲和⼒传播算法

这篇博客发出来后,我用 Rust 复现代码出现问题。为此,我对对照了 sklearn 的相关代码,反复比较了两天,发现一处 bug,把 += 误写成了 =,导致数据量大的时候完全无法聚类。这个debug过程让我仔细梳理的 AP 算法的计算过程,今天我对这篇博客做了大规模修改,以便能原样展现原论文思想。

程序猿视角 3219

智能气象站:ESP32驱动的心知天气数据可视化实践

本文详细介绍了基于ESP32微控制器和心知天气API构建智能气象站的完整实践。通过Arduino开发环境,实现天气数据的获取、JSON解析与OLED屏可视化展示,涵盖硬件连接、API配置、低功耗优化及部署问题排查,为物联网开发者提供实用指南。

jump7的博客 210

Recursive Type Bounds

How do I decrypt "Enum<E extends Enum<E>>"? As a type that can only be instantiation for its subtypes, and those subtypes will inherit some useful methods, some of which take subtype argu...

wengminyu的博客 265

LVI-SAM适配KITTI数据集避坑指南:IMU频率与数据同步问题解析

本文深入解析了将LVI-SAM框架适配KITTI数据集时,在IMU频率与多传感器数据同步方面遇到的核心挑战与解决方案。针对KITTI数据集中sync与extract两种数据包的差异,文章提供了从数据选择、参数调优到时间戳诊断与修复的完整避坑指南,帮助开发者实现稳定高效的SLAM系统部署。

7z8x2c4v6b9的博客 247

haskell学习笔记(6)-Parameterised types与Recursive types

看了两本书《haskell趣学指南》《real world haskell》,都对这里语焉不详。根据我自己的理解,Parameterised types就是其他语言中泛型在一个函数式语言中的特殊表示法。这两本书都出现了下面一段代码,而没有详细的解释data Maybe a = Just a | Nothing用比较熟悉的词汇来说,Maybe就是一个类名,a是泛型参数名,类似

o83290102o5的博客 581

Fiddler everywhere的一些基础操作

网上能搜到的Fiddler everywhere使用教程太少,于是我整理了一些自己实操成功的内容,包括Fiddler everywhere的Mock测试、弱网测试等基础操作,后续还会持续更新。操作系统:macOS使用工具:Fiddler everywhere 5.10.0本文简单介绍了使用Fiddler everywhere进行的Mock测试和弱网测试,而Fiddler everywhere提供了更多的其他实用的功能,我会在后期进行一个持续的学习和更新。

weixin_44346646的博客 2478

SAP数据导入工具(LSMW) 超级详细教程(批量导入内部订单)

用户提了个需求,让我批量导入内部订单几百个内部订单。我本打算用写段ABAP 代码来调用 BAPI (BAPI_INTERNALORDER_CREATE)就可以了。但想到我很久没有用过LSMW 了,都快要忘记了。于是我采用LSMW的方式,完成了任务。并把过程记录下来,形成教程方便我以后回头查看,分享出来也希望对大家有帮助。

IT小职员 2万+

Recursive Type Bond

求集合中最大的元素 private static <T extends Comparable<T>> T max(Collection<T> collection){ if(collection == null || collection.isEmpty()){ throw new IllegalArgumentExcep...

greywolf5的博客 155

windows下使用Nginx搭建Rtmp流媒体服务器,实现视频直播功能

一、环境介绍 操作系统:win10 64位系统 Linux下搭建Nginx搭建Rtmp流媒体服务器方法请看这里:https://blog.youkuaiyun.com/xiaolong1126626497/article/details/105378894 二、流媒体服务器介绍 流媒体服务器的主要功能是以流式协议(RTP/RTSP、MMS、RTMP等)将视频文件传输到客户端,供用户在线观看;也可从视频采集、压缩软件接收实时视频流,再以流式协议直播给客户端。 nginx服务器是开源的高性能的http服务器,反向

1万+

【学习Android NDK开发】Type Signatures(类型签名)

类型签名(Type Signatures)     (&lt;Parameter 1 Type Code&gt;[&lt;Parameter 1 Class&gt;];...)&lt;Return Type Code&gt; The JNI uses the Java VM’s representation of type signatures. Following Table shows t...

weixin_34198453的博客 196

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

scala recursive value x$5 needs type

recursive value x$5 needs type的原因是使用了一个类型不确定的变量,例如 val (id, name) = (id, getName(id))  其中id是个变量,其值还不确定, 就在getName(id)方法上使用.。例子不合理,但是一般这个报错就是代码写错了。...

weixin_33860528的博客 1593

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Scala 类型的类型(一)

目录 1. Scala 类型的不同类型 2. 写作进度 3. Type Ascription 4. 通用类型系统 — Any, AnyRef, AnyVal 5. 底类型 - Nothing 与 Null 1. Scala 类型的不同类型 2013 年在几场 「JavaOne 大会」之后,掀起了一些关于 「Sca

学亮编程手记 2373

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

深入理解Scala默认参数函数:从方法重载到优雅API设计

我写这篇文章的时候,特意没罗列默认参数有多少种用法——因为用法很简单,谁都能写。默认参数为什么重要?可选参数。Java里你想要可选参数?写重载方法。想要几个?写一堆。代码臃肿,维护痛苦。Scala的默认参数把这件事简化了——一行函数签名,编译器帮你生成所有的重载方法。调用方想用默认值就用默认值,想改哪个就改哪个,不用管顺序。把重复的事情交给编译器,让程序员专注在业务逻辑上。你不用手写重载方法——编译器帮你写。你不用记参数顺序——命名参数帮你记。你不用写Builder类——默认参数就是Builder。

https://starzy1990.github.io/ 744

深入理解Scala嵌套函数:作用域封装之道

我写这篇文章的时候,特意没罗列嵌套函数有多少种写法——因为写法很简单,谁都能写。嵌套函数为什么重要?辅助逻辑的作用域应该是多大?Java里你写辅助逻辑,只能写到类级别——因为Java的方法必须定义在类级别。但很多辅助逻辑其实只属于某一个函数,不属于整个类。你把它们写到类级别,就造成了作用域放大——本来应该是函数内部的东西,变成了类级别的东西。Scala的嵌套函数把这个问题解决了——辅助逻辑可以精确地封装在主函数内部。它直接访问外层函数的变量,不用把上下文传来传去。它不暴露到类级别,不造成API膨胀。

https://starzy1990.github.io/ 732

深入理解Scala可变参数函数:从Java数组语法到优雅集合传递

我写这篇文章的时候,特意没罗列可变参数有多少种用法——因为用法很简单,谁都能写。Scala的可变参数为什么比Java好用?不是因为它有:_*这个语法——而是因为它的底层是Seq,不是数组。Java的可变参数是数组的语法糖——你传List进去,它不认,因为List不是数组。你想传?自己转。Scala的可变参数是Seq的语法糖——你传任何序列进去,只要用:_*展开就行。不用转,不用强转,一行代码搞定。**这就是函数式语言的设计哲学:可变参数不是"数组的便捷写法",它是"序列的便捷写法"。

https://starzy1990.github.io/ 438

深入理解Scala Map:从实现原理到工程实践

我写这篇文章的时候,特意没罗列Map有多少个方法——因为那些东西官方文档都有,查一下就行。Map到底解决了什么问题?它不是"带key的列表",它是一个"从key到value的映射函数"。它用哈希表的O(1)查找,换来了通过key快速找到value的能力。在大数据开发里,Map无处不在——维度关联、配置映射、计数统计、分组聚合、缓存索引。理解了Map,你就理解了大数据处理里最核心的几个操作:查找、映射、聚合。很多人用了几年Map,还停留在"new一个HashMap,然后put put put"的阶段。

https://starzy1990.github.io/ 389

深入理解Scala匿名函数:函数式编程基石

我写这篇文章的时候,特意没罗列匿名函数有多少种写法——因为写法很简单,谁都能写。匿名函数为什么是函数式编程的基石?把函数当参数传。你不能把函数当参数传,就没有map、filter、reduce这些集合操作。没有这些集合操作,就没有声明式编程。没有声明式编程,就没有函数式编程。Java花了很长时间才意识到这一点——Java 8才加了Lambda。但Java的Lambda是不完整的——它只能捕获final变量,不能修改变量。它是一个"阉割版"的闭包。Scala呢?

https://starzy1990.github.io/ 500

Scala List操作:不可变链表的函数式美学

Scala的List,表面上是Java List的"Scala版",本质上是函数式编程的核心数据结构——不可变的链表,配合模式匹配和递归,构成了声明式数据处理的基础。天然线程安全:不可变对象不需要锁,在多线程环境下可以安全共享结构共享:操作List时可以复用大部分结构,性能更好函数式友好:map/filter/reduce不修改原List,可以组合、可以嵌套这些特性不是孤立的,它们共同支撑了Scala的函数式编程范式。

https://starzy1990.github.io/ 1336

【Spark】 04键值对 RDD:创建、常用操作与数据分区

介绍 Spark 键值对 RDD 的创建方式、聚合、分组、连接、排序与行动操作,并结合 PageRank 示例讲解数据分区、分区器复用与自定义分区方式。

qq_46126258的博客 368

大数据Spark(八十二):Spark 算子综合案例

本文通过四个典型Spark算子应用案例,系统讲解了单词频次过滤、PV/UV统计、二次排序及分组取TopN的实现方法。涵盖flatMap、mapToPair、reduceByKey、distinct、sortByKey、groupByKey等核心算子的组合使用,提供Java与Scala双语言实现,兼顾可读性与实用性。强调根据数据规模选择合适方案,避免内存溢出,适用于大数据处理场景的实战参考。

Lansonli(蓝深李)的博客 612

深入理解Scala递归函数:从栈溢出到尾调用优化

我写这篇文章的时候,特意没罗列递归有多少种写法——因为递归的语法很简单,谁都能写。为什么Java的递归会栈溢出,而Scala的不会?不是因为Scala更厉害——而是因为Scala是函数式语言,递归是它的核心特性之一。它从设计之初就考虑了尾调用优化的问题。Java是命令式语言,它的核心是对象和方法,递归只是一个"能用但不推荐"的特性。Java程序员写递归:栈溢出,不敢用Scala程序员写递归:尾递归,随便写递归不是洪水猛兽,栈溢出是因为你没写对。你可以用递归的优雅写法,获得循环的性能。

https://starzy1990.github.io/ 613

深入理解Scala可变Map:动态构建场景下的性能与设计权衡

我写这篇文章的时候,特意没罗列可变Map有多少个方法——因为那些东西官方文档都有,查一下就行。为什么需要可变Map?不是因为"它就是Java HashMap的Scala版",而是因为在动态构建数据的场景下,不可变Map的性能不够好。你要在循环里不断往Map里加key-value对,用不可变Map就是O(n²)的灾难,用可变Map就是O(n)的高效。但可变Map也不是万能的。它只适合"构建"场景——你在一个方法内部,动态构建一个Map,最后输出一个不可变Map。

https://starzy1990.github.io/ 360
上一篇: Running the balancer in Cloudera Hadoop
下一篇: Scala: Linearization technique to avoid multiple inheritance
DViewer
博客等级 码龄16年 16粉丝 6原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值