我正试图通过项目Morte来探索和理解构造计算的领域。我知道可以在Agda中表示这样的数据类型,但是对于我来说如何在这样的极简主义环境中表示它并不明显。怎么可能这样呢?我的意思是这个数据类型,在Idris中:
data Tree : Nat -> Type -> Type where
Leaf : a -> Tree Z a
(::) : Tree k a -> Tree k a -> Tree (S k) a
答案 0 :(得分:5)
我不知道Morte的细节,但我有一些线索可以更广泛地了解类型lambda-calculi的可能性。
如果Nat
被无法定义,则可以通过迭代定义这些树。
Nat : *
Nat = (x : *) -> (x -> x) -> x -> x
Pair : * -> * -> *
Pair x y = (z : *) -> (x -> y -> z) -> z
Tree : * -> Nat -> *
Tree a n = n * (\ t -> Pair t t) a
当然,为了逃避这一点,我需要消除大。在这里,我随便采取* : *
,但这一般不安全。归纳定义可以毫无疑问地允许大量消除:不可预测编码的数据类型,不是这样。
但是,上面,我利用了这样一个事实,即树的索引结构恰好与索引它们的Nat
的索引结构兼容,并且没有理由说这一般情况应该如此。指数各种各样古怪的方式各不相同:它只是那些表征某种“大小”的方式。随着我们向内走,它会变小。
索引结构确实允许教会编码演示。它不是迭代一个集合,而是迭代一个索引集。这是表达它的一种方式。
Tree : * -> Nat -> *
Tree a n = (x : Nat -> *) ->
(a -> x Z) ->
((n : Nat) -> x n -> x n -> x (S n)) ->
x n
写一些像
这样的东西很容易leftmost : (a : *) -> (n : Nat) -> Tree a n -> a
leftmost a n t = t (\ _ -> a) (\ a -> a) (\ _ l _ -> l)
但
leftChild : (a : *) -> (n : Nat) -> Tree a (S n) -> Tree a n
是一个更高的订单,需要一些方法来检查或约束数字。这就是为什么GHC Haskell拥有关于平等的所有这些东西,~
。
答案 1 :(得分:3)
我所看到的Morte,一切都是使用Church编码编码的。例如。列出您链接的帖子的示例:
data List a = Cons a (List a) | Nil
编码为
type List a = forall x . (a -> x -> x) -> x -> x
依赖类型的第一个例子是长度索引列表又名矢量:
data Vec a (n :: Nat) where
VNil :: forall a. Vec a 0
VCons :: forall a (n :: Nat). a -> Vec n a -> Vec (S n) a
这种野兽的教会编码是什么?我不知道哪种思维启发式对您有用, 你必须亲自发现它。
我的思维方式:Vector与list非常不同。它更像是n-ary homogeous 元组。几个例子编码:
type Singleton a = forall x. (a -> x) -> x -- Vec a 1
type Pair a = forall x. (a -> a -> x) -> x -- Vec a 2
type Triple a = forall x. (a -> a -> a -> x) -> x -- Vec a 3
模式很明显。我们需要的是从自然数到类型族的函数:
nTupleType a 0 x = x
nTupleType a 1 x = a -> x = a -> nTupleType a 0 x
nTupleType a 2 x = a -> (a -> x) = a -> nTupleType a 1 x
nTupleType a n x = ... -- General equation is left as an exercise
鉴于此,我们可以编码Vec
:
type Vec a n = forall x. nTupleType a n x -> x
vnil = \x -> x
vcons (a : *) (n : Nat) (h : a) (t : Vec a n) = \x f -> t x (f h) -- I'm not sure if I got this right
使用类似的方法,您可以编码其他索引数据结构。对于原始问题:完全平衡的树,编码看起来非常相似,nTupleType
必须从线性变为指数(0,1,2,3, ...)
到(1, 2, 4, 8, ...)
。
值得注意的是,树的实际形状将隐藏在Morte中:Tree a n ~ Vec a (exp2 n)
。 OTOH是Morte的观点。我想。