我正在尝试在F#中创建函数,在下图中,我正在尝试创建一个函数,该函数接受一个float列表并求和该列表中的值。我不知道如何在函数中将列表作为参数传递,所以我尝试使用此方法来获取列表的头,但是代码不起作用:
let sumlist l=
printf "%f" l.Head
然后我看到有人这样做:
let sumlist l:float=
match l with
| [] -> 0.0
| e::li -> e + sumlist li
l:float
是将列表传递给函数的方式吗?像l:string
这样的字符串列表?
但是我看到列表l具有l.Head
函数来返回列表中的第一个元素(似乎我们无法像数组一样访问列表中的任意元素),但是
let sumlist l:float=
printfn "%f" l.Head
给出类型不匹配错误。
我也不理解所提供的递归代码,我不理解这一行
| e::li -> e + sumlist li
什么是::?和李?
谢谢您为我澄清一下!
答案 0 :(得分:1)
因此,第一个示例不返回任何内容,这是因为您正在调用printfn,该命令会打印到控制台而不是返回您的类型。 e :: li这里表示一个列表,其中e是头,li是列表的其余部分。 ::这里让编译器知道您要解构列表。
//fully annotated
let s (l: float list) :float =
l.Head
//here the types can be inferred without any annotation
let rec sumlist l =
match l with
| [] -> 0.0
| e::li -> e + sumlist li
s [0.7]
//returns 0.7
sumlist [0.4;0.5;0.6]
//returns 1.5
在我的第一个示例中,如果尝试删除类型注释,则会发现出现错误。这是因为l.Head的类型是模棱两可的,否则您是否在字符串列表(浮点数)上调用了l.Head?在我提供的sumlist函数中,您可以看到我不需要注释,这是因为我将它们加起来并限制了类型。
就个人而言,我强烈建议始终对类型进行注释。 (l : float list)
或(l: list<float>)
是说我的输入是浮点数列表的一种方式,而:float
最后是我们说返回类型是浮点数的方式。您会注意到我在递归函数上放置了rec关键字,最好在进行递归函数时显式声明。
答案 1 :(得分:1)
l:float是将列表传递给函数的方式吗?
不。多数情况下,编译器可以确定您在传递列表时未将参数注释为列表,但是如果没有通过注释,则注释为
l : 'a list // where 'a is generic type
// OR
l : float list // where type is specified as float
什么是::?和李?
当模式匹配列表时,[]匹配到空列表,此处用作递归结束条件。另一个匹配将头(e)与列表的其余部分(尾)(li)分开。如果列表中只有一项,则li的值为[]。
递归代码的附加说明:例如,您缺少递归关键字 rec 。
let rec sumlist ...
最简单的方法是使用sum function of List例如。
[0.4; 0.5; 0.6] |> List.sum // Returns 1.5
但是,如果要自己创建此函数,请考虑使用tail-recursion以获得更好的性能,并避免使用较大的输入列表来避免堆栈溢出。
let sumlist (values : float list) =
let rec sum (acc : float) (remaining : float list) =
match remaining with
| [] -> acc
| head :: tail -> sum (acc + head) tail
sum 0. values
被称为
[0.4; 0.5; 0.6] |> sumlist // Returns 1.5
与常规递归不同的是,每个递归都计算自己的值,并且不依赖于其他递归尚未完成计算。