【问题标题】:Something is really wrong with either ADT theory or how it is treated in programming languages?ADT 理论或它在编程语言中的处理方式真的有问题吗?
【发布时间】:2013-11-17 19:50:25
【问题描述】:

我不是数学家,但我觉得存在一些逻辑问题。

让我们从 ADT 原语开始,例如“unit”类型。它应该在类型集的上下文中扮演“1”的角色。但实际上,我们在 C、C++ 等中看到“unit”类型通常被称为“void”等价物。同时我们在 ADT 中有自己的“void”类型,它扮演“0”的角色,实际上定义自身的 NO 值。

对此的一些观点听起来像“单元类型不带来任何信息,因此它是无用的,我们可以将其视为 void-like”。但是 C void 等价物在哪里?或者,void = unit,“0=1”?引入一些悖论是个坏主意。

然后,让我们更深入。单位类型只定义一个值,好吧。但是,为什么在 ADT 理论中

unit + unit = 2*unit

我们什么时候应该得到单位? “+”的工作方式类似于“或”定义我们称为变体类型的类型。 “单位或单位”绝对不会给我们“位”,或者任何更复杂的东西来继续。

提到 haskell 元组,它甚至没有单个元素的元组,但可以为空。 所以它也来自ADT理论。元组是项类型的乘法,因此一个元素元组与那个裸元素相同,空元组是单位值()。

a == (a) == ((a)) == ...
() == (()) == ...

所以,这里有一个悖论:空元组的长度是多少?可以看到,它的长度同时是零和一……

【问题讨论】:

标签: haskell algebraic-data-types type-theory unit-type


【解决方案1】:

首先,我们需要忽略类 C 语言等:它们甚至不尝试匹配数学基础。

Haskell 和其他函数式语言确实尝试过这一点,虽然它们的同构如何工作通常并不明显。

然后,让我们更深入。单位类型只定义一个值,好吧。但是,为什么在 ADT 理论中

unit + unit = 2*unit

我们什么时候应该得到单位? “+”的工作方式类似于“或”定义我们称为变体类型的类型。 “单位或单位”绝对不会给我们“位”或任何更复杂的东西来继续。

嗯,是的,它确实给了我们一些东西。

type Bit = Either () ()

(||), (&&) :: Bit -> Bit -> Bit

(Left()) || (Left()) = Left()
_ || _ = Right()

(Right()) && (Right()) = Right()
_ && _ = Left()

如果你不相信它有效:

Prelude Acme.Missiles> type Bit = Either () ()
Prelude Acme.Missiles> let [true, false] = [Left (), Right ()] :: [Bit]
Prelude Acme.Missiles> if true==false then launchMissiles else return ()
正在加载包 stm-2.4.2 ... 正在链接 ... 完成。
正在加载包 acme-missiles-0.3 ... 正在链接 ... 完成。
Prelude Acme.Missiles>

啊,谢天谢地,我们还活着……


至于“嵌套单元元组”:那些只是代表1ⁿ ≡ 1.


当我们真正考虑零类型时,也许事情会变得更清楚。

{-# LANGUAGE EmptyDataDecls #-}

data Void

现在,让我们来看看最简单的情况:

  • 0*0 = 0。由于我们无法为元组的任一侧提供值,因此我们无法定义 (Void, Void) ≅ Void 类型的值。
  • 0+0 = 0。虽然Either 提供了两个构造函数,但都需要一个我们无法提供的Void 参数,所以我们仍然有Either Void Void ≅ Void
  • 0*1 = 0。我们无法构造(Void, ()),因为我们无法为fst 提供值。
  • 0+1 = 1。啊哈!我们不能构造Left,但我们可以构造Right ()!所以Either Void () ≅ (),因为那是这种类型的单一值。
  • 1*1 = 1。元组的两边只能取值()
  • 1+1 = 2。这就是我上面讨论的情况,它具有不同的值 Left ()Right ()
  • 2+3 = ... 该死,I've chosen the wrong programming language for explaining this! 顺便说一句,⟂ 就出来了...

【讨论】:

  • 不,没有什么特别的。只是 ADT 理论中的 +not 像“或”一样工作,Haskell 中的 Either 也没有:它跟踪使用哪个字段,无论两者是否具有相同的类型. ——“元组的长度”没有定义,所以没有理由谈论这个。
  • @user3002392 不,它们不一样。它们包含相同数量的信息,但它们是可区分的。这就像说 True 和 False 是相同的,因为它们传达的信息量相同。
  • @user3002392: (a,b,c,d)((a,b),(c,d)) 同构,所以你同样可以说它的长度是 2。
  • 这些元组与任何“相似列表”都不同构。 — 当然,Haskell 将这些类型视为不同的类型是对的,但这发生在类型系统级别。类型系统只是为我们提供了一个框架,我们可以在其中拥有 ADT 对象的代表。 OTOH,对于(a,b,c,d)((a,b),(c,d)),“它是不同的值”的说法没有意义:这些类型的值既不能相等也不能不同,因为类型系统不允许我们== 它们。但是存在(忽略⟂)一个唯一同构sp :: (a,b,c,d)->((a,b),(c,d)),WRT,它们是相同的。
  • @user3002392 如果您不考虑“它们的包装器”(它们与其他任何东西一样是价值的一部分),那么您将不再拥有 ADT。 ADT 的优势在于能够组合类型和区分不同的组合。想象一下,如果您无法区分 Left "Unexpected symbol on line 3, column 5"Right "if x == 5:" 之间的区别,Either 将多么无用——我们将再次只使用字符串!
猜你喜欢
  • 2018-05-10
  • 1970-01-01
  • 2015-01-08
  • 1970-01-01
  • 1970-01-01
  • 2023-04-07
  • 1970-01-01
  • 1970-01-01
  • 2020-07-19
相关资源
最近更新 更多