当前位置: 首页 > 知识库问答 >
问题:

Haskell Singletons:我们从SNat中得到了什么

山疏珂
2023-03-14
data Nat = Zero | Succ Nat

到目前为止还不错!

使用GADT语法,他还定义了数据类型SNAT:

data SNat :: Nat -> * where
  SZero :: SNat Zero
  SSucc :: SNat n -> SNat (Succ n)

基本上,他只将Nat类型包装到一个SNat构造函数中。为什么要这样做呢?我们有什么收获?数据类型Nat和SNat不同构吗?为什么SNat是单身,为什么Nat不是单身?在这两种情况下,每个类型都有一个值,即相应的自然数。

共有1个答案

东方英豪
2023-03-14

我们有什么收获?嗯。单身人士的地位是尴尬的,但目前是必要的变通办法,我们越早消除他们越好。

让我看看我能不能把这幅画弄清楚。我们有一个数据类型NAT:

data Nat = Zero | Suc Nat

(战争的起因甚至比suc中的'c'数更琐碎)

if <b> then <t> else <e>
if <b> then <e> else <t>

在运行时和类型级的NAT之间没有直接的交换方式,这可能是一个麻烦。范例涉及向量上的一个关键操作:

data Vec :: Nat -> * -> * where
  VNil   :: Vec 'Zero x
  VCons  :: x -> Vec n x -> Vec ('Suc n) x

我们可能希望计算给定元素的副本向量(可能作为applicative实例的一部分)。这看起来是个好主意

vec :: forall (n :: Nat) (x :: *). x -> Vec n x

但那能起作用吗?为了使某些东西具有n副本,我们需要在运行时了解n:程序必须决定是部署vnil并停止,还是部署vcons并继续运行,它需要一些数据来完成这一操作。一个很好的线索是forall量词,它是参数的:它表示量化的信息只对类型可用,并且被运行时擦除。

vec :: pi (n :: Nat) -> forall (x :: *). Vec n x
vec 'Zero    x = VNil
vec ('Suc n) x = VCons x (vec n x)
data SNat :: Nat -> * where
  SZero :: SNat Zero
  SSuc  :: SNat n -> SNat (Suc n)

现在,szerossuc生成运行时数据。SNATNAT不同构:前者具有NAT->*类型,而后者具有*类型,因此试图使它们同构是一种类型错误。NAT中有许多运行时值,类型系统不区分它们;在每个不同的snatn中正好有一个运行时值(值得一提),因此类型系统无法区分它们的事实是无关紧要的。关键是每个SNATn对于每个不同的n都是不同的类型,并且GADT模式匹配(其中模式可以是已知匹配的GADT类型的更具体实例)可以改进我们对n的了解。

我们现在可以写信了

vec :: forall (n :: Nat). SNat n -> forall (x :: *). x -> Vec n x
vec SZero    x = VNil
vec (SSuc n) x = VCons x (vec n x)

单例允许我们在运行时和类型级数据之间架起桥梁,它利用了运行时分析的唯一形式,可以细化类型信息。想知道它们是否真的有必要是相当明智的,而它们目前是必要的,只是因为这一差距尚未消除。

 类似资料:
  • 使用HttpServletRequestWrapper包装HttpServletRequest的目的是什么?我们这样做有什么好处?

  • 不深入Kotlin语言(我们会在下一章再去学习),这里有一些Java中没有的有趣的特性: 易表现 通过Kotlin,可以更容易地避免模版代码因为大部分的典型情况都在语言中默认覆盖实现了。举个例子,在Java中,如果我们要典型的数据类,我们需要去编写(至少生成)这些代码: public class Artist { private long id; private String na

  • 我使用的是SPARK-SQL-2.4.1、SPARK-Cassandra-Connector2.11-2.4.1和java8以及apache Cassandra3.0版本。 我有如下所示的spark-submit或spark集群环境,可以加载20亿条记录。 当我检查日志时,我看到警告com.datastax.spark.connector.writer.QueryExecutor-BusyPool

  • 我是Spock测试框架的新手,我试图为我正在工作的一个android项目做一些测试。我目前测试的这些对象是PJO,所以可以用常规的Spock测试它们。出于某种原因,我一直在我的一个对象上调用isAlive方法,但我知道它被调用了,感觉我已经在调试器中运行了它,它被调用了。所以我希望有人能引导我知道我做错了什么。 下面是我的测试代码: 任何帮助都将不胜感激。我已经在我能想到的每种配置中尝试过了...

  • 我用下面的代码在我的WordPress网站上获得了WooCommerce形式的产品类别列表: 这工作正常,并返回产品类别的列表。我现在一直试图得到一个特定类别的产品列表。 示例:使用获取的所有产品。 我知道产品是作为帖子存储的,并且一直在努力做到这一点,但似乎做不到。 如何获取特定类别的产品列表?

  • 我有财产课: 还有一种方法: 在类的构造函数我有: 为什么当我从object按键调用函数时。我收到一条未定义的消息,为什么变量在内部不可用: