2015-11-13 164 views
1

我正在尝试在F#中的列表中查找最小元素。这里是我的代码:比较F中列表中的元素#

let rec list_minl lst = 
    match lst with 
    | [] -> failwith "Empty list" 
    | hd -> hd 
    | hd::tl when hd < tl -> list_minl tl 

但是当我运行程序这个错误出来:

FS0001: Type mismatch. Expecting a 
    'a  
but given a 
    'a list  
The resulting type would be infinite when unifying ''a' and ''a list' 

为什么?

+0

此功能已存在于F#核心库中:[List.min](https://msdn.microsoft.com/zh-cn/library/ee353412)。 –

回答

1

这里有很多问题 - 但我只是解决眼前的问题。

hd::tl when hd < tl 

比较hd这是一个元素,tl这是一个列表。您想比较hd与最小的tl

1

正如@John Palmer在他的回答中所述,您当前的代码将类型T的元素与类型T的列表进行比较,该列表无法工作。

我假设你想从数字列表中找到最小的数字。一个可能的解决办法是使用蓄电池的最低值(因为你需要保留在每个迭代上目前发现的最小的值):

let rec list_minl lst min = 
    match lst with 
    | h1::tl when h1 > min -> list_minl tl min 
    | h1::tl when h1 < min -> list_minl tl h1 
    | h1::tl (* when h1 = min *) -> list_minl tl min 
    | [] -> min 

累加器的初始值,例如可以是第一从列表元素:

let lst = [10;5;2;5;100;6;3] 
list_minl lst (List.head lst) |> Console.WriteLine 

输出是:

2 

你可以隐藏recursiv e功能和初始分钟。值,以便list_min只接受一个参数(列表):

let rec list_minl lst = 
    let rec ilist_minl lst min = 
     match lst with 
     (* if first element is bigger than current min, preserve min *) 
     | h1::tl when h1 > min -> ilist_minl tl min 
     (* if first element is smaller than current min, new min is current first element *) 
     | h1::tl when h1 < min -> ilist_minl tl h1 
     (* first element equals min, preserve min *) 
     | h1::tl (* when h1 = min *) -> ilist_minl tl min 
     (* processing is done *) 
     | [] -> min 

    ilist_minl lst (List.head lst) 

list_minl [10;5;2;5;100;6;3] |> Console.WriteLine 

输出与上面相同。

+1

使用Int32.MaxValue作为固定的提供值使得该功能非常具体。 min函数严格需要的唯一一个概念是大于和小于,因此为什么内置List.min具有签名'List.min:'T list - >'T(需要比较)'。您可以轻松使用列表中的第一个值作为比较的基础。 – TheInnerLight

+0

@TheInnerLight你是正确的 - 谢谢你的提示。我更改了示例代码。 – pasty