Преобразование C # код в F # (если утверждение)
Вопрос
Я хотел бы знать, как преобразовать этот код построчно от 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
Что такое проблема, действительно?
Решение
Если вы хотите преобразовать его линейку по строке, попробуйте следующее
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
И, конечно, вы должны абсолютно прочитать статью Брайана по этому вопросу. Это очень подробно и проходит многие из более тонких точек на перевод между двумя языками
Другие советы
Есть несколько проблем с вашим литеральным переводом. Прежде всего, есть немедленная проблема, которая вызывает ошибку компилятора: поскольку другие отметили, пусть привязки неизменяются по умолчанию. Тем не менее, есть хотя бы одна большая проблема: System.Collections.Generic.List<T>
сильно отличается от F # 't list
. Отказ Тип BCL представляет собой сметный список, поддерживаемый массивом, который обеспечивает постоянное время случайного доступа к элементам; Тип F # является неизмеренным в одиночном списке, поэтому доступ к NT-элементу принимает 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
Функция, которая эквивалентна.
Краткий ответ: =
не (Musable) назначение в f #.
Вопрос: Вы действительно имеете в виду col
?
Предложения: попробуйте написать это без назначений. В вашем распоряжении есть рекурсионные и встроенные функции :-)
Вы должны прочитать
Как этот код C # выглядит в F #? (Часть одна: выражения и высказывания)
Я разочарован тем, что ни один из других ответов уже не связал его, потому что люди просят многое значение C # на F # '', и я уже разместил этот ответ, и теперь некоторые другие ответы должны знать это :)
Это самый буквальный перевод.
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