我刚刚开始使用F *,我的意思是我在教程中写了几行。到目前为止,它真的很有趣,我想继续学习。
我自己尝试做的第一件事就是编写一个代表非空列表的类型。这是我的尝试:
type nonEmptyList 'a = l : (list 'a) { l <> [] }
但是我收到了错误
验证隐式参数失败:子类型检查失败;预期 type(#6468:输入{(hasEq a @ 0)});得到类型
我知道我在正确的轨道上,因为如果我将列表类型限制为包含字符串,则 工作:
type nonEmptyList = l : (list string) { l <> [] }
我假设这意味着原始示例中的l <> []
无效,因为我没有指定'a
应该支持相等。问题是,我不能为我的生活弄清楚如何做到这一点。我想这与名为hasEq
的更高级别的东西有关,但尝试的事情如下:
type nonEmptyList 'a = l : (list 'a) { hasEq 'a /\ l <> [] }
没有让我到任何地方。本教程不涉及hasEq
,我在GitHub仓库中的示例中找不到任何有用的东西,所以现在我卡住了。
答案 0 :(得分:4)
您在此处正确识别了问题。您在'a
定义中使用的类型nonEmptyList
未指定,因此无法支持相等性。你的直觉是正确的,你需要通过在其上添加一个改进来告诉F * 'a
是一个具有相等性的类型:
为此,您可以编写以下内容:
type nonEmptyList (a:Type{hasEq a}) = l : (list a) { l <> [] }
请注意,我用于该类型的活页夹是a
而不是'a
。它会导致语法错误,它更有意义,因为它不是&#34;任何&#34;再打字了。
另请注意,如果需要,您可以更精确地将a
类型的Universe指定为Type0
。
答案 1 :(得分:3)
您的分析确实是正确的,并且接受的答案通常会提供正确的解决方案。
但是,对于您的具体示例,您不需要列表元素上的可判定的相等性:您可以使用(list 'a){ ~ (List.isEmpty l) }
。
供参考,以下是isEmpty
:
(** [isEmpty l] returns [true] if and only if [l] is empty *)
val isEmpty: list 'a -> Tot bool
let isEmpty l = match l with
| [] -> true
| _ -> false