Преобразование кода C # в F # (оператор if) - PullRequest
5 голосов
/ 25 июня 2010

Я хотел бы знать, как преобразовать этот код строка за строкой из 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

В чем проблема, на самом деле?

Ответы [ 5 ]

14 голосов
/ 25 июня 2010

Если вы хотите преобразовать его построчно, попробуйте следующее

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 # имеет как минимум 2 формы, которые мне известны.

// Assigning to a mutable value
let mutable v1 = 42
v1 <- 13

// Assigning to a ref cell
let v1 = ref 0
v1 := 42

И, конечно, вы должны обязательно прочитать статью Брайана на эту тему.Он очень подробный и охватывает многие тонкости перевода между двумя языками

6 голосов
/ 25 июня 2010

Есть несколько проблем с вашим буквальным переводом.Прежде всего, существует непосредственная проблема, которая вызывает ошибку компилятора: как уже отмечали другие, пусть привязки по умолчанию неизменны.Однако есть по крайней мере еще одна большая проблема: System.Collections.Generic.List<T> очень отличается от F # 't list.Тип BCL является изменяемым списком, поддерживаемым массивом, который обеспечивает постоянный произвольный доступ к элементам;тип F # является неизменяемым односвязным списком, поэтому доступ к n-му элементу занимает O (n) времени.Если вы настаиваете на переводе с выражением по выражению, вы можете найти этот пост в блоге Брайана ценным.

Я настоятельно рекомендую вам следовать советам других и попытаться акклиматизироваться.думать в идиоматическом 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

Обратите внимание, что это работает со списками любого типа элемента (с оговоркой, что тип элемента должен быть comparable с точки зрения F # илиприменение функции приведет к ошибке времени компиляции).Если вам нужна версия, которая будет работать с любым типом последовательности, а не только со списками, вы можете основывать ее на функции Seq.reduce, которая применяет функцию, предоставленную в качестве первого аргумента, к каждой паре элементов в последовательности до единогозначение остается.

let getMin s = Seq.reduce min s

Или, что лучше всего, вы можете использовать встроенную функцию Seq.min, которая эквивалентна.

5 голосов
/ 25 июня 2010

Краткий ответ: = не является (изменяемым) назначением в F #.

Вопрос: Вы действительно имеете в виду col?

Предложения: Попытайтесь написать это без НО назначений.В вашем распоряжении есть рекурсивные и встроенные функции: -)

4 голосов
/ 25 июня 2010

Вы должны прочитать

Как этот код C # выглядит в F #?(часть первая: выражения и заявления)

Я разочарован тем, что ни один из других ответов уже не связал его, потому что люди часто задают вопрос «как преобразовать C # в F #», и я опубликовалэтот ответ связывают много, и теперь некоторые другие ответчики должны знать это:)

3 голосов
/ 26 июня 2010

Это самый буквальный перевод:

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
...