我正在构建一个比较两个列表的简单函数,如果第一个列表是第二个列表的前缀,则返回 true
。
预期签名:
prefix: int list -> int list -> bool
例如:
prefix [1; 2] [1; 2; 3; 4] --> true
prefix [ ] [1;2] --> true
prefix [2] [1;2;3] --> false
现在,我正处于这一步:
let prefix l1 l2 =
match l1 with
| (l1, l2) when (l1.[0] = l2.[0]) -> true
| _ -> false
我认为我的方法可能是正确的,但我遇到了这个错误:
The operator 'expr.[idx]' has been used on an object of
indeterminate type based on information prior to this program point. Consider adding
further type constraints
如何在 prefix
中声明 l1
和 l2
是列表?我寻找解决方案 here但问题可能是如此微不足道,以至于我没有答案。
最佳答案
为了回答关于声明类型是列表的问题的最后一部分(因为其他部分已经回答),我们使用“类型注释”。它们在函数参数中看起来像 (name : type)
,例如
let prefix (l1 : _ list) (l2 : _ list) = ...
这会将 l1
和 l2
声明为编译器将推断的某种类型的列表。您也可以根据需要将 _
替换为特定类型或通用类型。
要手动实现您的功能,请记住您需要做的不仅仅是比较第一个元素 - 您需要递归遍历列表。
let prefix l1 l2 =
let rec loop = function
| [], _ -> true
| _, [] -> false
| h1 :: _, h2 :: _ when h1 <> h2 -> false
| _ :: t1, _ :: t2 -> loop (t1, t2)
loop (l1, l2)
这个版本根本不需要类型注释,因为 loop
中的模式匹配将两个参数都限制为 'a list
类型。但是,如果您希望您的函数明确地只用于 int list
,您可以改为使用
let prefix (l1 : int list) l2 =
您只需要注释一个参数,因为另一个参数被限制为同一类型。
关于list - 在 F# 中声明类型列表参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40572925/