I'd like to know how to convert this code line by line from C# to F#. I am not looking to use any kind of F#'s idioms or something of the like. I am trying to understand how to map directly C#'s constructs to F#.
Here is the C# code:
//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;
}
And here is my F# attempt:
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
Now, this ain't working. The problem seems to be related with the minVal = col.Item(i)
line:
This expression was expected to have type unit but here has type bool
What is the problem, really?
If you want to convert it line by line then try the following
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
Now as to why you're getting that particular error. Take a look at the following line
minVal = col.Item(i)
In F# this is not an assignment but a comparison. So this is an expression which produces a bool value but inside the for
loop all expressions must be void
/unit
returning. Hence you receive an error.
Assignment in F# has at least 2 forms that I am aware of.
// Assigning to a mutable value
let mutable v1 = 42
v1 <- 13
// Assigning to a ref cell
let v1 = ref 0
v1 := 42
And of course, you should absolutely read Brian's article on this subject. It's very detailed and goes over many of the finer points on translating between the two languages
There are a few problems with your literal translation. First of all, there's the immediate problem which causes the compiler error: as others have noted, let bindings are immutable by default. However, there's at least one other big problem: System.Collections.Generic.List<T>
is very different from F#'s 't list
. The BCL type is a mutable list backed by an array, which provides constant time random access to elements; the F# type is an immutable singly linked list, so accessing the nth element takes O(n) time. If you insist on doing expression-by-expression translation, you may find this blog post by Brian valuable.
I'd strongly recommend that you follow others' advice and try to acclimate yourself to thinking in idiomatic F# rather than literally translating C#. Here are some ways to write some related functions in 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
Note that this works on lists of any element type (with the caveat that the element type needs to be comparable
from F#'s perspective or the application of the function will cause a compile-time error). If you want a version which will work on any type of sequence instead of just on lists, you could base it on the Seq.reduce
function, which applies the function supplied as its first argument to each pair of elements in a sequence until a single value remains.
let getMin s = Seq.reduce min s
Or best of all, you can use the built-in Seq.min
function, which is equivalent.
Short answer: =
is not (mutable) assignment in F#.
Question: Do you really mean col
?
Suggestions: Try to write this with NO assignments. There is recursion and built-in functions at your disposal :-)
You should read
What does this C# code look like in F#? (part one: expressions and statements)
I am disappointed that none of the other answers already linked it, because people ask the 'how to convert C# to F#' question a lot, and I have posted this answer link a lot, and by now some of the other answerers should know this :)
This is the most literal translation possible:
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
来源:https://stackoverflow.com/questions/3120478/converting-c-sharp-code-to-f-if-statement