Haskell 类型可存储的确切标准是什么?
很久以前,我为对称组(和循环组)实现了一种数据类型:Haskell 类型可存储的确切标准是什么?,haskell,containers,gadt,data-kinds,Haskell,Containers,Gadt,Data Kinds,很久以前,我为对称组(和循环组)实现了一种数据类型: newtype Cyclic (n :: Nat) = Cyclic {cIndex :: Integer} data Symmetric (n :: Nat) where S1 :: Symmetric 1 (:.) :: Cyclic n -> Symmetric (n-1) -> Symmetric n 这是一个不均匀的容器,但我不确定这是数组还是列表。正如评论所阐明的,这不是一个问题 如果这是一个数组
newtype Cyclic (n :: Nat) = Cyclic {cIndex :: Integer}
data Symmetric (n :: Nat) where
S1 :: Symmetric 1
(:.) :: Cyclic n -> Symmetric (n-1) -> Symmetric n
这是一个不均匀的容器,但我不确定这是数组还是列表。正如评论所阐明的,这不是一个问题
如果这是一个数组,则可以实现
实例可存储(对称n)
。究竟为什么可能这样做?可存储的旨在唤起Cstruct
s的思想。作为一个结构
,任何可存储的类型
都有大小限制可存储(对称n)
是可能的,因为对称n
实际上是有界大小。(假设循环n
s是等价的模n
),它有n代码>值,这是有限的,因此不需要无界空间。更具体地说,只要log2(n!)
位就足够了。注意,对于某些特定的n
,我谈论的是symmetricn
。对于不同的Nat
sn
,m
等,symmetricn
,symmetricm
等是不同的类型,因此它们可能具有不同的大小。对于单个n::Nat
,对称n
具有固定大小
真正的问题是选择编码。为了便于实现,您可以使用递归编码,其中可存储的n
由ceil(log2(n)/8)
字节组成,以保存第一个数字,后跟可存储的(n-1)
。然后,Symmetric 1
将是0字节,Symmetric 2
将是1字节(只使用了一位),Symmetric 3
将是2字节,Symmetric 256
将是255字节,Symmetric 257
将是257字节(因为第一个数字有257个选项,因此需要两个字节)。这当然不是很有效,但您可以清楚地看到,每个对称n
都有一个定义良好的大小。如果你想深入到log2(n!)
bits(真的,ceil(log2(n!)/8)
bytes)的范围,你必须做一些~~~funkymath~~(我不熟悉),但你可以做到
你需要单身人士来做这件事;写作是可能的
instance KnownNat n => Storable (Symmetric n)
但不是
instance Storable (Symmetric n)
类型被擦除,因此第二个实例
不会被告知n
是什么,因此无法读取任何内容(或实现sizeof
等)。它可以写,因为Symmetric
是GADT,因此包含关于n
是什么的信息
旁注:对称0不应该是非空的吗
data Symmetric (n :: Nat) where
S0 :: Symmetric 0
(:.) :: Cyclic n -> Symmetric (n - 1) -> Symmetric n
Symmetric 0
是从空集到自身的双射集,其中只有一个函数(空集)。它是一个列表,但这与能够编写可存储的
实例有点正交。@leftaroundabout我想知道原因。(作为答案)@左撇子要具体,我不知道哈斯克尔是怎么知道的“正交”。“dnundoOS”在“Haskell”和“C++”之间的区别并不重要,因为在C(和C++)中存储数据的位置在Haskell中是重要的。在Haskell中,“true”数组(连续存储)非常罕见;它们可以在数组
和向量
库中找到,但除非性能变得重要,否则通常不会使用它们。正常的Haskell类型[]
是一个链表;大多数其他容器在内部实现为某种形式的树。在本例中,您正在将对称
实现为一个链表。@DannyuNDos和至于“正交”注释,leftaroundabout只是说它是否是一个列表与编写可存储
实例的问题无关。循环n
具有整数
是否无关,无界大小?A循环n
表示从0
到n-1
的数字。从逻辑上讲,这是一个有限数量的值,因此有一个有限大小的编码。您决定将其实现为一个整数
,这一事实与此无关。例如,您可以说数据循环n,其中CZ::循环1;CS::Cyclic n->Cyclic(sn)
并在其上构建相同的逻辑。取决于您如何处理它,例如,Cyclic 10::Cyclic 5
要么无效,要么被视为等于Cyclic 0
。无论哪种方式,您都不关心范围0
到n-1
之外的任何内容。