Создаем список
В F# есть несколько путей, которыми Вы можете создать список.
- Создаём пустой список
- Создаем простой список с элементами от 1 до 10
- Создаем список с нечетными номерами в промежутке от 1 до 10
- Используем цикл for для создания списка
let prettyPrint desc list = printfn desc printfn "%A" list //empty list let listEmpty = [] //simple list let list1 = [1 .. 10 ] //simple list, with step value let list2 = [1 ..2..10 ] //using for loops to create lists let list3 = [for i in 1 .. 10 -> i*2 ] prettyPrint "let listEmpty = []" listEmpty prettyPrint "let list1 = [ 1 .. 10 ]" list1 prettyPrint "let list2 = [ 1 .. 2..10 ]" list2 prettyPrint "[ for i in 1 .. 10 -> i*2 ]" list3

В последнем примере, показанном выше, показано, как использовать цикл for для создания списка, что очень круто, но в наборе инструментов F # есть что-то еще более крутое и мощное, а именно «List Comprehensions».
List Comprehensions(понимание списков?) — это мощный метод, который позволяет вам создавать списки, используя в значительной степени стандартный F#, который включает функции / циклы / условия и т.д.
Давайте продолжим смотреть на пример того, как мы могли бы создавать списки.
let is2 x = match x with | 2 -> "YES" | _ -> "NO" //yield directly let list1 = [ yield 1; yield 2; yield 3; ] //yield numbers between 1 and 20 where we use the //Math.Pow function to return a new number let list2 = [for i in 1.0 .. 20.0 do yield Math.Pow(i,2.0) ] //yield only numbers between 1 and 20 that //can be divided by 5 let list3 = [ for i in 1 .. 20 do if i % 5 = 0 then yield i ] //yields YES/NO strings depending on //whether source int = 2 or not let list4 = [for i in 1 .. 5 -> is2 i ]

Некоторые полезные операторы списков
Оператор Cons
Мы можем использовать оператор cons «::» для добавления значений в существующий список, поэтому предположим, что у нас был этот список:
let list1 = [1;2;3;4] let list2 = 42 :: list1

Оператор конкатенации
Другим весьма полезным оператором является оператор «@», который позволяет объединять списки одного типа. Так, например, если бы у нас было это:
let list1 = [1;2;3;4] let list2 = [5;6;7;8] let list3 = list1 @ list2

Модуль List
Я не думаю, что перебарщиваю, когда говорю, что модуль List является ключевым модулем в F#. Фактически, документация MSDN для него очень хороша по сравнению с другими в F#. Поэтому я не думаю, что смогу добавить много полезного к примерам, найденным на MSDN, но я приведу здесь несколько для вашего удобства, но для получения дополнительной информации вы должны изучить MSDN.
Свойства
Head
‘T
Первый элементEmpty
‘T list
Возвращает пустой список, заданного типаIsEmpty
bool
true — если в списке нет элементов
Item
‘T
Элемент, который находится по специфическому индексу
Length
int
Количество элементов
Tail
‘T list
Список без первого элемента:
let list1 = [ 1; 2; 3 ] // Properties printfn "list1.IsEmpty is %b" (list1.IsEmpty) printfn "list1.Length is %d" (list1.Length) printfn "list1.Head is %d" (list1.Head) printfn "list1.Tail.Head is %d" (list1.Tail.Head) printfn "list1.Tail.Tail.Head is %d" (list1.Tail.Tail.Head) printfn "list1.Item(1) is %d" (list1.Item(1))

Фильтр(filter)
Возвращает новую коллекцию, содержащую только элементы коллекции, для которой данный предикат возвращает true. Вот тривиальный пример, который выбирает только четные числа из списка для создания нового списка
let evenOnlyList = List.filter (fun x -> x % 2 = 0) [1; 2; 3; 4; 5; 6]

Поиск(find)
Возвращает первый элемент, для которого данная функция возвращает true. В этом примере, поскольку список от 1 до 100 содержит 5, 5 — это 1-е число, которое делится на 5, поэтому это возвращаемое значение:

Для всех(forall)
Проверяет, все ли элементы коллекции удовлетворяют данному предикату. В этом примере весь список должен содержать 0, чтобы получить истинное возвращаемое значение.
let isAllZeroes list = List.forall (fun elem -> elem = 0.0) list printfn "%b" (isAllZeroes [0.0; 0.0]) printfn "%b" (isAllZeroes [0.0; 1.0])

Применить ко всех(Iteri)
Применяет данную функцию к каждому элементу коллекции. Целое число, переданное функции, указывает на индекс элемента.
let data = ["Cats";"Dogs";"Mice";"Elephants"] data |> List.iteri (fun i x -> printfn "item %d: %s" i x)

Сортировать по(SortWith)
Сортирует указанный список, используя данную функцию сравнения.
let list1 = [ ""; "&"; "&&"; "&&&"; ""; "|"; "||"; "|||" ] printfn "Before sorting: " list1 |> printfn "%A" //custom sorting function let sortFunction (string1:string) (string2:string) = if (string1.Length > string2.Length) then 1 else if (string1.Length printfn "After sorting:\n%A"

В модуле списка есть множество полезных функций, это лишь малая часть того, что можно найти.
Небольшой взгляд на рекурсию над списками
Никакое обсуждение списков не будет полным без разговора о рекурсии.Рекурсия — это то, чему будет посвящен целый пост, но сейчас давайте рассмотрим, что нужно, чтобы написать рекурсивную функцию, которая работает над списком в F#.
let printIt desc x = printfn "%A %A" desc x let rec printList list = match list with | h :: t -> printIt "head=" h printIt "tail=" t printList t | [] -> () printList [1;2;3;4;5]
Обратите внимание на использование ключевого слова rec , которое сообщает компилятору F #, что эта функция будет рекурсивной. Без этого ключевого слова рекурсивный вызов функции — Вы получите сообщение о ошибке компиляции, хотя и с не очень понятным текстом о ошибке.

Итак, давайте посмотрим результаты выполнения примера, показанного чуть выше со следующим списком [1; 2; 3; 4; 5]

Можно видеть, что все работает просто отлично, и оно прекращает работу, когда значение соответствует пустому списку, как и ожидалось.

