我正在构建一个比较两个列表的简单函数,如果第一个列表是第二个列表的前缀,则返回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,但问题可能很小,我没有答案。
答案 0 :(得分:3)
要回答关于声明类型是列表的问题的最后部分(因为已经回答了其他部分),我们使用"类型注释"。它们在函数参数中看起来像(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 =
您只需要注释一个参数,因为另一个参数被限制为相同类型。
答案 1 :(得分:2)
我认为这有一个通用的List函数:
let prefix l1 l2 =
List.compareWith (fun x y -> if x = y then 0 else 1) l1 l2 < 0
答案 2 :(得分:1)
使用l.[0]
时,实际上是在尝试使用数组。
我会使用像
这样的东西|(h1::t1,h2::t2) when h1=h2 -> true
但是在这里,匹配并不是你想要的 - 你需要
match (l1,l2) with
因为你匹配两个列表