有人可以解释依赖打字给我吗?我在Haskell,Cayenne,Epigram或其他函数式语言方面没有经验,所以您可以使用的术语越简单,我越会感激它!什么是依赖型打字?
回答
想一想:在所有正常的编程语言中,您都可以编写函数,例如
def f(arg) = result
这里,f
取值arg
并计算值result
。它是从值到值的函数。
现在,一些语言允许你定义多态(又名通用)值:
def empty<T> = new List<T>()
这里,empty
需要一个类型T
并计算值。它是从类型到值的函数。
通常情况下,你也可以有泛型类型定义:
type Matrix<T> = List<List<T>>
这个定义需要一个类型,它返回一个类型。它可以被看作是从类型到类型的函数。
对于普通语言提供的东西太多了。如果一种语言也提供了第四种可能性,那么它就被称为从属类型,即从数值到类型定义函数。或换句话说,参数化一个值的类型定义:
type BoundedInt(n) = {i:Int | i<=n}
一些主流语言有一些假的形式,这是不会混淆的。例如。在C++中,模板可以将值作为参数,但在应用时它们必须是编译时常量。一种真正的依赖型语言并非如此。例如,我可以使用上面的类型是这样的:
def min(i : Int, j : Int) : BoundedInt(j) =
if i < j then i else j
编辑:在这里,函数的结果类型取决于实际参数值j
,这样的术语。
尽管“BoundedInt”示例实际上不是“精化类型”吗?这个'非常接近',但不完全是那种'依赖类型',例如,Idris在关于dep.typing的教程中首先提到。 – Noein 2015-06-29 22:32:57
@Noein,精化类型的确是一种依赖类型的简单形式。 – 2015-06-30 18:00:55
竞标书的类型和编程语言(30.5):
本书很多一直关注正式抽象不同种类的 机制。在简单类型的lambda演算中,我们 将抽取一个术语和抽象出一个 子项的操作形式化,产生一个函数,稍后可以通过 将其应用于不同的术语。在系统
F
中,我们考虑了 采取一个术语并抽象出一种类型的操作,产生一个术语 ,可以通过将其应用于各种类型来实例化该术语。在λω
中,我们 概括了简单类型的lambda演算“一级 级别”的机制,采用一种类型并抽象出一个子表达式,以获得一个类型运算符,该运算符稍后可以通过将其应用于不同类型来实例化。所有这些抽象形式的简便思维方式都是根据表达式的家族来表达的,其他 表达式。普通拉姆达抽象λx:T1.t2
是 术语[x -> s]t1
的系列,其由术语s
索引。类似地,类型抽象λX::K1.t2
是按类型索引的术语族,并且类型操作符 是按类型索引的类型族。
λx:T1.t2
家庭方面的通过方面
λX::K1.t2
家庭条件的按种类
λX::K1.T2
通过类型看着这个列表索引类型的家庭收录索引,很显然,我们有一种可能性是 还没有考虑到:按条款索引的类型家族。这种抽象的形式也被广泛研究,依赖于依赖类型的 。
如果你碰巧知道C++可以很容易地提供一个激励例如:
比方说,我们有一些容器类型和两个实例及其
typedef std::map<int,int> IIMap;
IIMap foo;
IIMap bar;
,并考虑下面的代码片段(您可能假设foo是非空的):
IIMap::iterator i = foo.begin();
bar.erase(i);
这是明显的垃圾(可能会破坏数据结构s),但它会进行类型检查,因为“iterator into foo”和“iterator into bar”是相同的类型,即使它们在语义上完全不兼容。
问题是一个迭代器类型不应该仅仅依赖于容器类型,但其实在容器上对象,也就是说,它应该是一个“非静态成员类型”:
foo.iterator i = foo.begin();
bar.erase(i); // ERROR: bar.iterator argument expected
这样一个特性,即表达一个依赖于词(foo)的类型(foo.iterator)的能力,正是依赖类型意味着的。
你不经常看到这个功能的原因是因为它打开了一大堆蠕虫:你在编译时检查两种类型是否相同的情况下突然终止证明两个表达式是等价的(在运行时总会产生相同的值)。因此,如果您将维基百科的list of dependently typed languages与其list of theorem provers进行比较,您可能会注意到可疑的相似性。 ;-)
相关类型使logic errors的较大集合能够在编译时间被消除。为了说明这一点考虑功能f
以下规范:
功能
f
必须采取只甚至整数作为输入。
没有相关的类型,你可以做这样的事情:
def f(n: Integer) := {
if n mod 2 != 0 then
throw RuntimeException
else
// do something with n
}
在这里,编译器不能如果n
检测确实是偶数,也就是说,从编译器的角度来看,有以下公式确定:
f(1) // compiles OK despite being a logic error!
该程序会运行,然后在运行时抛出异常,也就是说,您的程序有逻辑错误。
现在,依赖类型让你成为更富于表现力,并能使你写这样的事情:
def f(n: {n: Integer | n mod 2 == 0}) := {
// do something with n
}
这里n
依赖型{n: Integer | n mod 2 == 0}
的。它可以帮助阅读了这一点,大声
n
是一个整数集的成员,使得每个整数整除 2.
在这种情况下,编译器会检测到在编译时一个逻辑错误,你已经通过一个奇数到f
,并且会阻止程序首先被执行:
f(1) // compiler error
- 1. 什么是Maven依赖
- 2. 什么是依赖注入?
- 3. 与依赖打字
- 4. 什么是Spring对依赖注入的最小依赖?
- 5. 路径依赖类型和依赖类型之间有什么区别?
- 6. 什么是链接的向上依赖?
- 7. pom依赖项中的springfox是什么?
- 8. 什么是android.media.tv的依赖关系
- 9. 什么是GcmTaskService(GCM)的依赖关系?
- 10. Pynxc的依赖包是什么?
- 11. 是什么导致循环依赖?
- 12. 什么都是最终的jar依赖?
- 13. 什么是依赖查找和Ioc的
- 14. JavaScript中的“依赖实现”是什么?
- 15. maven依赖项的名称是什么?
- 16. Apache Ignite:IgniteHadoopIgfsSecondaryFileSystem的依赖关系是什么?
- 17. 什么是preg_match_all“u”标志依赖于?
- 18. 什么是WPF中的依赖属性
- 19. 什么是PHP中的“包”依赖?
- 20. 什么是“可选”Maven依赖关系?
- 21. 什么是“手动依赖注入”?
- 22. Xpand最小的pom依赖是什么?
- 23. 什么意思是依赖注入?
- 24. 什么是应用依赖注入
- 25. 什么是隐藏的依赖关系?
- 26. 什么是目标依赖项?
- 27. 解决依赖问题是什么?
- 28. 什么是jboss-client.jar maven依赖关系?
- 29. 什么是ntpd的systemd依赖关系?
- 30. 什么是Android中的依赖关系?
是的。这通常是我开始我所有的学习。 – Nick 2012-02-18 05:31:13
那你到底知道些什么?维基百科文章? – 2012-02-19 04:28:34
好吧,文章以lambda立方体打开,这听起来像是某种羊肉给我的。然后它继续讨论λΠ2系统,并且因为我不会说外星人,所以我跳过了这一部分。然后,我读到了关于归纳结构的演算,这似乎与微积分,热传递或构造无关。在给出一个语言比较表后,文章就结束了,我比我进入页面时更加困惑。 – Nick 2012-02-19 05:50:49