我想知道如何将此代码逐行从C#转换为F#。我不打算使用任何一种F#的习语或类似的东西。我试图了解如何将C#的构造直接映射到F#。
这是C#代码:
//requires l.Length > 0
int GetMinimumValue(List<int> l) {
int minVal = l[0];
for (int i = 0; i < l.Length; ++i) {
if (l[i] > minValue) {
minVal = l[i];
}
}
return minVal;
}
这是我的F#尝试:
let getMinValue (l : int list) =
let minVal = l.Head
for i = 0 to (l.Length-1) do
if (l.Item(i) > minVal) then
minVal = col.Item(i)
minVal
现在,这不起作用。问题似乎与minVal = col.Item(i)
行有关:
This expression was expected to have type unit but here has type bool
问题是什么,真的吗?
答案 0 :(得分:14)
如果您想逐行转换,请尝试以下
let getMinValue (l:System.Collections.Generic.List<int>) =
let mutable min = l.Item(0)
for i = 0 to (l.Count-1) do
if l.Item(i) < min then min <- l.Item(i)
min
现在你为什么会得到那个特定的错误。看一下以下一行
minVal = col.Item(i)
在F#中,这不是作业,而是比较。所以这是一个产生bool值的表达式,但在for
循环内,所有表达式都必须返回void
/ unit
。因此,您收到错误。
F#中的作业至少包含两种我所知道的形式。
// Assigning to a mutable value
let mutable v1 = 42
v1 <- 13
// Assigning to a ref cell
let v1 = ref 0
v1 := 42
当然,你应该完全阅读Brian关于这个主题的文章。它非常详细,并且在两种语言之间进行翻译有很多细节
答案 1 :(得分:6)
您的直译有一些问题。首先,存在导致编译器错误的直接问题:正如其他人所指出的那样,默认情况下让绑定是不可变的。但是,至少还有一个重大问题:System.Collections.Generic.List<T>
与F#的't list
非常不同。 BCL类型是一个由数组支持的可变列表,它提供对元素的恒定时间随机访问; F#类型是一个不可变的单链表,因此访问第n个元素需要O(n)时间。如果您坚持进行逐个表达式的翻译,您可能会发现this blog post by Brian有价值。
我强烈建议您遵循他人的建议,尽量让自己适应惯用语F#,而不是直接翻译C#。以下是在F#中编写一些相关函数的一些方法:
// Given an F# list, find the minimum element:
let rec getMinList l =
| [] -> failwith "Can't take the minimum of an empty list"
| [x] -> x
| x::xs ->
let minRest = getMin xs
min x minRest
请注意,这适用于任何元素类型的列表(从F#的角度来看,元素类型需要为comparable
,或者函数的应用程序将导致编译时错误)。如果你想要一个适用于任何类型的序列而不仅仅是列表的版本,你可以将它建立在Seq.reduce
函数上,该函数将作为第一个参数提供的函数应用于序列中的每对元素,直到单个值仍然存在。
let getMin s = Seq.reduce min s
或者最重要的是,您可以使用内置的Seq.min
函数,它等效。
答案 2 :(得分:5)
简短回答:=
在F#中不是(可变的)赋值。
问题:你的意思是col
吗?
建议:尝试使用NO分配来编写此代码。您可以使用递归和内置函数: - )
答案 3 :(得分:4)
你应该阅读
What does this C# code look like in F#? (part one: expressions and statements)
我很失望其他答案都没有联系到它,因为人们会问'如何将C#转换为F#'这个问题很多,而且我已经发布了很多这个答案链接,现在还有一些其他的回答者应该知道这一点:)
答案 4 :(得分:3)
这是最直接的翻译:
let getMinimumValue (l: List<int>) =
let mutable minVal = l.[0]
for i=0 to l.Length-1 do
if l.[i] > minVal then
minVal <- l.[i]
minVal