我是依赖类型的新手,并且拥有Haskell经验,我正在慢慢学习Idris。对于一个练习,我想写一个霍夫曼编码。目前我正试图写一个证明"展平"代码树产生了前缀代码,但却被量词所困扰。
我有一个简单的归纳命题,一个列表是另一个列表的前缀:
using (xs : List a, ys : List a)
data Prefix : List a -> List a -> Type where
pEmpty : Prefix Nil ys
pNext : (x : a) -> Prefix xs ys -> Prefix (x :: xs) (x :: ys)
这是一种有效的方法吗?或者类似&#34; xs 是 ys 的前缀,如果有 zs 那样 xs ++ < em> zs = ys &#34;会更好吗?
这是引入&#34; forall&#34;的正确方法。量词(据我所知,在Agda中它会像pNext : ∀ {x xs ys} → Prefix xs ys → Prefix (x :: xs) (y :: ys)
)? pNext第一个参数应该隐含吗?两种变体之间的语义差异是什么?
然后,我想为一个向量构建一个向量,其中没有元素形成另一个元素的前缀:
data PrefVect : Vect n (List a) -> Type where
空向量没有前缀:
pvEmpty : PrefVect Nil
给定一个元素x,一个向量xs,并证明xs的任何元素都不是x的前缀(反之亦然),x :: xs将保存该属性:
pvNext : (x : [a]) -> (xs : Vect n [a]) ->
All (\y => Not (Prefix x y)) xs ->
All (\y => Not (Prefix y x)) xs ->
PrefVect (x :: xs)
这是一个无效的类型,我希望在处理第一个类型之后修复,但pvNext中有关于量词的类似问题:这个变体是否可以接受,或者有更好的方法来形成&#34;否定关系&#34;
谢谢。
答案 0 :(得分:3)
我认为这里唯一的问题是你在Haskell风格中使用[a]
作为a
列表的类型,而在Idris中它必须是{{1} }。
我的List a
类型对我来说很好,尽管我将它写成:
Prefix
也就是说,data Prefix : List a -> List a -> Type where
pEmpty : Prefix [] ys
pNext : Prefix xs ys -> Prefix (x :: xs) (x :: ys)
可能是隐含的,您不需要x
,因为Idris可以推断出using
和xs
的类型。这是否是正确的方法实际上取决于您打算使用ys
类型的计划。它当然很容易测试列表是否是另一个列表的前缀。类似的东西:
Prefix
如果你想证明你可能会出现的否定,你需要这种类型:
testPrefix : DecEq a => (xs : List a) -> (ys : List a) -> Maybe (Prefix xs ys)
testPrefix [] ys = Just pEmpty
testPrefix (x :: xs) [] = Nothing
testPrefix (x :: xs) (y :: ys) with (decEq x y)
testPrefix (x :: xs) (x :: ys) | (Yes Refl) = Just (pNext !(testPrefix xs ys
testPrefix (x :: xs) (y :: ys) | (No contra) = Nothing
我将这一个留作练习:)。