Idris的类型驱动开发介绍了这个练习:
same_cons : {xs : List a} -> {ys : List a} -> xs = ys -> x :: xs = x :: ys
但是,我试图通过以下方式实现它:
data EqList : (xs : List a) -> (ys : List a) -> Type where
Same : (xs: List a) -> EqList xs xs
sameS : (xs : List a) -> (ys : List a) -> (x: a) -> (eq : EqList xs ys) -> EqList (x :: xs) (x :: ys)
sameS xs xs x (Same xs) = Same (x :: xs)
same_cons : {xs : List a} -> {ys : List a} -> (eq : EqList xs ys) -> EqList (x :: xs) (x :: ys)
same_cons {xs} {ys} eq = sameS xs ys _ eq
我推断了x
中的EqList (x :: xs) (x :: ys)
,因为如果x
和xs
为空,我很难理解如何获得ys
。
此外,上面的编译,但当我试图调用它时失败了:
*Exercises> same_cons (Same [1,2,3])
(input):Can't infer argument x to same_cons
答案 0 :(得分:2)
在您的用例中无法推断出隐式参数x
,因为调用same_cons (Same [1,2,3])
中没有信息可以将其约束为任何内容。如果您修改了结果的类型,那么您将可以选择x
,例如
λΠ> the (EqList [0,1,2,3] [0,1,2,3]) (same_cons (Same [1,2,3]))
Same [0, 1, 2, 3] : EqList [0, 1, 2, 3] [0, 1, 2, 3]
因为[0,1,2,3]
选择x:xs
将x
与0
统一起来。
顺便说一下,您可以简化same_cons
的定义,因为eq
参数的类型决定了xs
和ys
,所以您可以让Idris推断它:
same_cons : (eq : EqList xs ys) -> EqList (x :: xs) (x :: ys)
same_cons eq = sameS _ _ _ eq
答案 1 :(得分:2)
澄清如何获得x
:
如果它不是已经明确的,那么类型decleration中的小写字母将成为隐式参数。所以
same_cons : {xs : List a} -> {ys : List a} ->
(eq : EqList xs ys) -> EqList (x :: xs) (x :: ys)
与
相同same_cons : {a : Type} -> {x : a} -> {xs : List a} -> {ys : List a} ->
(eq : EqList xs ys) -> EqList (x :: xs) (x :: ys)
x
隐藏的地方。因此,您可以使用定义左侧的{x}
来获取它。或者只是让伊德里斯处理所有的东西并使用Cactus'定义。对于参数的未来问题,您可以在REPL中使用:set showimplicits
在询问类型时显示所有隐式参数,例如: :t same_cons
。
当Idris无法推断隐式参数的值时,您可以通过给出类似Cactus的结果类型来帮助它,或者将隐式参数设置为值:
*> same_cons {x=0} (Same [3,2,5])
Same [0, 3, 2, 5] : EqList [0, 3, 2, 5] [0, 3, 2, 5]