在F#中声明类型列表参数

时间:2016-11-13 10:40:24

标签: list f#

我正在构建一个比较两个列表的简单函数,如果第一个列表是第二个列表的前缀,则返回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中声明l1l2是列表?我找了一个解决方案here,但问题可能很小,我没有答案。

3 个答案:

答案 0 :(得分:3)

要回答关于声明类型是列表的问题的最后部分(因为已经回答了其他部分),我们使用"类型注释"。它们在函数参数中看起来像(name : type),例如

let prefix (l1 : _ list) (l2 : _ list) = ...

这将声明l1l2作为编译器将推断的某种类型的列表。您也可以根据需要将_替换为特定类型或通用类型。

为了手动实现您的功能,请记住,您必须更进一步,而不仅仅是比较第一个元素 - 您需要通过列表进行递归。

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

因为你匹配两个列表