Idris-Can';t型评价函数的应用

Idris-Can';t型评价函数的应用,idris,unification,type-level-computation,Idris,Unification,Type Level Computation,我遇到了一个问题,我有一个类型为fun a的值,fun是一个函数,a是一个在类型检查时无法计算的值,当我强制它成为该函数应用程序的结果时,会抛出一个统一错误 具体错误如下: When checking right hand side of testRec2 with expected type Record [("A", String), ("C", Nat)] Type mismatch between Record (projectLeft ["A",

我遇到了一个问题,我有一个类型为
fun a
的值,
fun
是一个函数,
a
是一个在类型检查时无法计算的值,当我强制它成为该函数应用程序的结果时,会抛出一个统一错误

具体错误如下:

When checking right hand side of testRec2 with expected type
         Record [("A", String), ("C", Nat)]

 Type mismatch between
         Record (projectLeft ["A", "C"]
                             [("A", String),
                              ("B", String),
                              ("C", Nat)]) (Type of hProjectByLabels_comp ["A",
                                                                           "C"]
                                                                          testRec1
                                                                          (getYes (isSet ["A",
                                                                                          "C"])))
 and
         Record [("A", String), ("C", Nat)] (Expected type)

 Specifically:
         Type mismatch between
                 projectLeft ["A", "C"]
                             [("A", String), ("B", String), ("C", Nat)]
         and
                 [("A", String), ("C", Nat)]
这来自Idris中类似HList记录的实现,示例如下:

testRec1 : Record [("A", String), ("B", String), ("C", Nat)]
-- testRec1's value is already defined    

testRec2 : Record [("A", String), ("C", Nat)]
testRec2 = hProjectByLabels_comp ["A", "C"] testRec1 (getYes $ isSet ["A", "C"])
。。。以下类型:

IsSet : List t -> Type

isSet : DecEq t => (xs : List t) -> Dec (IsSet xs)

LabelList : Type -> Type

IsLabelSet : LabelList lty -> Type

HList : LabelList lty -> Type

Record : LabelList lty -> Type

recToHList : Record ts -> HList ts

recLblIsSet : Record ts -> IsLabelSet ts

hListToRec : DecEq lty => {ts : LabelList lty} -> {prf : IsLabelSet ts} -> HList ts -> Record ts

IsProjectLeft : DecEq lty => List lty -> LabelList lty -> LabelList lty -> Type

IsProjectRight : DecEq lty => List lty -> LabelList lty -> LabelList lty -> Type

hProjectByLabelsHList : DecEq lty => {ts : LabelList lty} -> (ls : List lty) -> HList ts -> ((ls1 : LabelList lty ** (HList ls1, IsProjectLeft ls ts ls1)), (ls2 : LabelList lty ** (HList ls2, IsProjectRight ls ts ls2)))

projectLeft : DecEq lty => List lty -> LabelList lty -> LabelList lty

hProjectByLabelsLeftIsSet_Lemma2 : DecEq lty => {ls : List lty} -> {ts1, ts2 : LabelList lty} -> IsProjectLeft ls ts1 ts2 -> IsLabelSet ts1 -> IsLabelSet ts2

fromIsProjectLeftToComp : DecEq lty => {ls : List lty} -> {ts1, ts2 : LabelList lty} -> IsProjectLeft ls ts1 ts2 -> IsSet ls -> ts2 = projectLeft ls ts1

hProjectByLabels_comp : DecEq lty => {ts : LabelList lty} -> (ls : List lty) -> Record ts -> IsSet ls -> Record (projectLeft ls ts)
。。。以及以下(必要)定义:

LabelList : Type -> Type
LabelList lty = List (lty, Type)

IsLabelSet : LabelList lty -> Type
IsLabelSet ts = IsSet (map fst ts) 

projectLeft : DecEq lty => List lty -> LabelList lty -> LabelList lty
projectLeft [] ts = []
projectLeft ls [] = []
projectLeft ls ((l,ty) :: ts) with (isElem l ls)
  projectLeft ls ((l,ty) :: ts) | Yes lIsInLs = 
    let delLFromLs = deleteElem ls lIsInLs
        rest = projectLeft delLFromLs ts
    in (l,ty) :: rest
  projectLeft ls ((l,ty) :: ts) | No _ = projectLeft ls ts

deleteElem : (xs : List t) -> Elem x xs -> List t
deleteElem (x :: xs) Here = xs
deleteElem (x :: xs) (There inThere) =
  let rest = deleteElem xs inThere
  in x :: rest 

getYes : (d : Dec p) -> case d of { No _ => (); Yes _ => p}
getYes (No _ ) = ()
getYes (Yes prf) = prf

hProjectByLabels_comp : DecEq lty => {ts : LabelList lty} -> (ls : List lty) -> Record ts -> IsSet ls -> Record (projectLeft ls ts)
hProjectByLabels_comp {ts} ls rec lsIsSet =
  let 
    isLabelSet = recLblIsSet rec
    hs = recToHList rec
    (lsRes ** (hsRes, prjLeftRes)) = fst $ hProjectByLabelsHList ls hs
    isLabelSetRes = hProjectByLabelsLeftIsSet_Lemma2 prjLeftRes isLabelSet
    resIsProjComp = fromIsProjectLeftToComp prjLeftRes lsIsSet
    recRes = hListToRec {prf=isLabelSetRes} hsRes
  in rewrite (sym resIsProjComp) in recRes
基本上,有一个函数
projectLeft
,应用于两个列表并返回一个新列表。
hProjectByLabels\u comp的类型在类型级别应用此功能。
为了实际构建结果列表,我有一个样式为
Pred l1 l3
的谓词和一个样式为
Pred l1 l3->l3=projectLeft l1 l2
的引理。在
hProjectByLabels\u comp
中,我将引理应用于谓词,并使用
rewrite
获得正确的类型签名(在这种特定情况下,将
l3
重写到
projectLeft l1 l2
projectLeft ls ts
中,它隐式地出现在实现内部的谓词中)

我希望对记录应用
hProjectByLabels\u comp
将正确计算
projectLeft ls ts
。但是,在上面的示例中,它无法计算/计算
projectLeft[“A”,“C”][(“A”,String),(“B”,String),(“C”,Nat)]
。这似乎有点奇怪,因为在REPL中评估该函数应用程序会准确地给出
[(“A”,String),(“C”,Nat)]
,这是类型所期望的,但Idris在类型检查时似乎无法计算该函数

我不确定一些引理/函数的实现是否与此有关,或者是否仅仅与类型有关

我尝试使用一个更简单的示例(在NAT上使用谓词和函数)复制此错误,但该更简单的示例类型检查正确,因此我找不到其他方法来复制此错误

我使用的是Idris 0.9.20.2

编辑:我尝试用以下方式重写
projectLeft
,查看是否有任何更改,但它始终显示相同的错误

projectLeft : DecEq lty => List lty -> LabelList lty -> LabelList lty
projectLeft ls [] = []
projectLeft ls ((l,ty) :: ts) with (isElem l ls)
  projectLeft ls ((l,ty) :: ts) | Yes lIsInLs = 
    let delLFromLs = deleteElem ls lIsInLs
        rest = projectLeft delLFromLs ts
    in (l,ty) :: rest
  projectLeft ls ((l,ty) :: ts) | No _ = projectLeft ls ts

projectLeft
是一个总功能吗?分部函数不会减少类型签名,也就是说,您只看到它们应用于其参数,而不是应用程序的结果

举例说明:

type : Int -> Type
type 0 = String

a : type 0
a = "Hello"

将无法编译,并出现类型错误,抱怨无法将
类型0
字符串匹配。尽管为相关值定义了函数
type
,但Idris拒绝在类型签名中应用部分函数。不过,您仍然可以在repl中应用它
type 0
给出了
String:type
,而
type 1
给出了
type 1:type
(未减少)。

显然,在更新到Idris 0.12后,这个问题现在得到了解决。没有更改任何内容,但它现在正在进行打字检查。

是的,它是总计。我甚至在我的文件头上有
%defaulttotal
。我看到
testRec1
没有分配任何值,这是故意的吗?否则,你不能依赖于内部有洞的东西的计算行为,这是故意的。该示例假设值
testRec1
已经存在(内部没有漏洞)。您可以提供完整示例的要点,还是使用更简单的要点?没有它就很难调试,因为到目前为止,其他一切都很好。