类型作为位
Elm 中有各种类型
Bool
Int
String
(Int, Int)
Maybe Int
- ...
我们现在对它们有概念上的理解,但计算机如何理解它们?Maybe Int
如何存储在硬盘上?
位
位是一种具有两种状态的小盒子。0 或 1。开或关。计算机内存是位的一串超长序列。
好的,我们所拥有的就是一堆位。现在我们需要用它来表示所有内容!
Bool
Bool
值可以是 True
或 False
。这完全对应于一位!
Int
Int
值是像 0
、1
、2
等整数。你无法将它放在一位中,因此唯一的其他选择就是使用多个位。因此,通常,Int
将是一个位序列,如下所示
00000000
00000001
00000010
00000011
...
我们可以任意地为每个序列指定意义。所以也许 00000000
是 0,00000001
是 1。太棒了!我们可以按升序开始向位序列分配数字。但最终我们会用光位...
通过一些快速的计算,8 位只允许 (2^8 = 256) 个数字。那么 9000 和 8004 等非常合理的数字又会怎么样呢?
答案是只需添加更多位。很长一段时间内,人们使用 32 位。这允许有 (2^32 = 4,294,967,296) 个数字,它涵盖了人类通常会想到的数字类型。如今的计算机支持 64 位整数,允许有 (2^64 = 18,446,744,073,709,551,616) 个数字。这很多!
注意:如果你好奇加法如何运作,请了解二进制补码。它揭示了数字并非随意分配给位序列。为了使加法尽可能快,这种分配数字的特定方式非常有效。
String
字符串"abc"
是字符a
b
c
的序列,因此我们将尝试将字符表示为二进制位序列。
早期的一种字符编码方式称为ASCII。与整数类似,它们决定列出一堆二进制位序列,并开始任意地分配值
00000000
00000001
00000010
00000011
...
因此每个字符需要由八个二进制位表示,这意味着只能表示 256 个字符!但如果你只关心英语,这实际上非常有效。你需要涵盖 26 个小写字母、26 个大写字母和 10 个数字。共有 62 个。还剩很多空间可用于符号和其他奇奇怪怪的东西。你可以看到他们最终得到了这里的内容。
现在我们对字符有了一个想法,但计算机如何知道String
在哪里结束以及下一条数据从哪里开始?这只是一些二进制位。字符看起来真得就像Int
值!因此,我们需要某种方法来标记结束。
如今,语言倾向于通过存储字符串的长度来实现此目的。因此,像"hello"
这样的字符串在内存中可能看起来像5
h
e
l
l
o
。因此,你知道一个String
始终以表示该长度的 32 个二进制位开头。无论长度是 0 还是 9000,你都知道字符的结束位置。
注意:在某种程度上,人们想涵盖英语之外的语言。这项工作最终导致了UTF-8编码。它确实非常出色,我鼓励你了解它。事实证明,“获取第 5 个字符”比听起来要难!
(Int, Int)
哪一个元组呢?好,(Int, Int)
是两个Int
值,每个值都是二进制位序列。让我们将这两个序列放在内存中的紧挨着,然后休息一下!
自定义类型
自定义类型全是关于组合不同类型。这些不同的类型可能具有各种不同的形状。我们从Color
类型开始
type Color = Red | Yellow | Green
我们可以为每个案例分配一个数字:Red = 0
、Yellow = 1
和Green = 2
。现在,我们可以使用Int
表示法。这里我们只需要两个二进制位来涵盖所有可能的情况,因此00
是红色、01
是黄色、10
是绿色,而11
则未使用。
但是,对于那些保存其他数据的自定义类型怎么办?像是Maybe Int
?典型的方法是预留一些二进制位来“标记”数据,这样我们可以决定Nothing = 0
和Just = 1
。以下是一些示例
Nothing
=0
Just 12
=1
00001100
Just 16
=1
00010000
case
表达式始终在决定下一步做什么之前查看这个“标签”。如果它看到一个 0
,则它知道没有更多数据。如果它看到一个 1
,则它知道后跟代表数据的一系列位。
这个“标签”的想法类似于将长度放在 String
值的开头。这些值大小可能不同,但代码始终可以弄清楚它们从哪里开始和结束。
摘要
最终,所有值都需要以位来表示。此页面粗略地概述了它的实际工作原理。
通常没有真正的理由去考虑这个,但我发现它有助于加深我对自定义类型和 case
表达式的理解。我也希望它对你有帮助!
注意: 如果你认为这很有趣,那么了解有关垃圾回收的更多信息可能会很有趣。我发现垃圾回收手册 是一个关于该主题的优秀资源!