Converting C# code to F# (if statement)

…衆ロ難τιáo~ 提交于 2020-01-02 03:50:27

问题


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?


回答1:


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

  • http://lorgonblog.spaces.live.com/Blog/cns!701679AD17B6D310!725.entry



回答2:


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.




回答3:


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 :-)




回答4:


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 :)




回答5:


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!