Парадигмы | Мультипарадигмальный : функциональный , императивный , объектно-ориентированный , агентно-ориентированный , метапрограммирование , рефлексивный , параллельный |
---|---|
Семья | ML : Caml : OCaml |
Разработано | Дон Сайм , Microsoft Research |
Разработчик | Microsoft , Фонд программного обеспечения F# |
Впервые появился | 2005 ( 2005 ) | , версия 1.0
Стабильный релиз | 9.0 [1] / 12 ноября 2024 г. ( 12 ноября 2024 ) |
Дисциплина набора текста | Статичный , сильный , предполагаемый |
ОС | Кроссплатформенность : .NET Framework, Mono |
Лицензия | Массачусетский технологический институт [2] [3] |
Расширения имени файла | .fs, .fsi, .fsx, .fsscript |
Веб-сайт | fsharp.org |
Под влиянием | |
C# , Erlang , Haskell , [4] ML , OCaml , [5] [6] Python , Scala | |
Под влиянием | |
C# , [7] Elm , F* , LiveScript | |
F# (произносится как F sharp ) — это универсальный , высокоуровневый , строго типизированный , многопарадигмальный язык программирования , охватывающий функциональные , императивные и объектно-ориентированные методы программирования. Чаще всего он используется как кроссплатформенный язык Common Language Infrastructure (CLI) на .NET , но также может генерировать код JavaScript [8] и графического процессора (GPU). [9]
F# разработан F# Software Foundation , [10] Microsoft и открытыми участниками. Открытый исходный код , кроссплатформенный компилятор для F# доступен в F# Software Foundation. [11] F# — полностью поддерживаемый язык в Visual Studio [12] и JetBrains Rider . [13] Плагины, поддерживающие F#, существуют для многих широко используемых редакторов, включая Visual Studio Code , Vim и Emacs .
F# является членом семейства языков ML и возник как реализация .NET Framework ядра языка программирования OCaml . [5] [6] На него также оказали влияние C# , Python , Haskell , [4] Scala и Erlang .
F# -версия | Спецификация языка | Дата | Платформы | Время выполнения |
---|---|---|---|---|
1.х | Май 2005 г. [14] | Окна | .NET 1.0 - 3.5 | |
2.0 | Август 2010 г. | Апрель 2010 г. [15] | Linux , MacOS , Windows | .NET 2.0 - 4.0, Моно |
3.0 | Ноябрь 2012 г. | Август 2012 [16] | Linux , macOS , Windows ; JavaScript , [8] Графический процессор [9] | .NET 2.0 - 4.5, Моно |
3.1 | Ноябрь 2013 г. | Октябрь 2013 г. [17] | Linux , macOS , Windows ; JavaScript , [8] Графический процессор [9] | .NET 2.0 - 4.5, Моно |
4.0 | Январь 2016 г. | Июль 2015 г. [18] | ||
4.1 | Май 2018 г. | Март 2017 г. [19] | Linux , MacOS , Windows , JavaScript , [8] Графический процессор [9] | .NET 3.5 - 4.6.2, .NET , Моно |
4.5 | Август 2018 [20] | Linux , MacOS , Windows , JavaScript , [8] Графический процессор [9] | .NET 4.5 - 4.7.2, [21] .NET Core SDK 2.1.400 [22] | |
4.6 | Март 2019 [23] | Linux , MacOS , Windows , JavaScript , [8] Графический процессор [9] | .NET 4.5 - 4.7.2, [24] .NET Core SDK 2.2.300 [25] | |
4.7 | Сентябрь 2019 [26] | Linux , MacOS , Windows , JavaScript , [8] Графический процессор [9] | .NET 4.5 - 4.8, [27] .NET Core SDK 3.0.100 [28] | |
5.0 | Ноябрь 2020 г. [29] | Linux , MacOS , Windows , JavaScript , [8] Графический процессор [9] | .NET SDK 5.0.100 [30] | |
6.0 | Ноябрь 2021 г. [31] | Linux , MacOS , Windows , JavaScript , [8] Графический процессор [9] | .NET SDK 6.0.100 [32] | |
7.0 | Ноябрь 2022 г. [33] | Linux , MacOS , Windows , JavaScript , [8] Графический процессор [9] | .NET SDK 7.0.100 [34] | |
8.0 | Ноябрь 2023 г. [35] | Linux , MacOS , Windows , JavaScript , [8] Графический процессор [9] | .NET SDK 8.0.100 [36] | |
9.0 | Ноябрь 2024 г. [37] | Linux , MacOS , Windows , JavaScript , [8] Графический процессор [9] | .NET SDK 9.0.0 [38] |
F# использует открытый процесс разработки и проектирования. Процессом эволюции языка руководит Дон Сайм из Microsoft Research в качестве благожелательного пожизненного диктатора (BDFL) для разработки языка совместно с F# Software Foundation. Более ранние версии языка F# были разработаны Microsoft и Microsoft Research с использованием закрытого процесса разработки.
F# впервые был включен в Visual Studio в издании 2010 года на том же уровне, что и Visual Basic (.NET) и C# (хотя и в качестве опции), и остается во всех более поздних изданиях, что делает язык широко доступным и хорошо поддерживаемым.
F# берет свое начало в Microsoft Research, Кембридж, Великобритания. Первоначально язык был разработан и реализован Доном Саймом , [5] по словам которого в команде fsharp говорят, что F означает «Веселье». [39] Эндрю Кеннеди внес вклад в разработку единиц измерения. [5] Visual F# Tools для Visual Studio разработаны корпорацией Microsoft. [5] F# Software Foundation разработала компилятор и инструменты F# с открытым исходным кодом, включив реализацию компилятора с открытым исходным кодом, предоставленную командой Microsoft Visual F# Tools. [10]
F# -версия | Добавлены функции |
---|---|
1.0 |
|
2.0 |
|
3.0 [40] |
|
3.1 [41] |
|
4.0 [42] |
|
4.1 [43] |
|
4.5 [29] |
|
4.6 |
|
4.7 [44] |
|
5.0 [45] |
|
6.0 [46] |
|
7.0 [47] |
|
8.0 [48] |
|
F# — это строго типизированный функционально-первый язык с большим количеством возможностей, которые обычно встречаются только в функциональных языках программирования , при этом поддерживая объектно-ориентированные функции, доступные в C#. Вместе эти функции позволяют писать программы на F# в полностью функциональном стиле, а также позволяют смешивать функциональные и объектно-ориентированные стили.
Примеры функциональных особенностей:
F# — это язык на основе выражений, использующий активное вычисление , а также в некоторых случаях ленивое вычисление . Каждое выражение в F#, включая if
выражения, try
выражения и циклы, является составным выражением со статическим типом. [52] Функции и выражения, которые не возвращают никаких значений, имеют возвращаемый тип unit
. F# использует let
ключевое слово для привязки значений к имени. [52] Например:
пусть х = 3 + 4
привязывает значение 7
к имени x
.
Новые типы определяются с помощью type
ключевого слова. Для функционального программирования F# предоставляет типы tuple , record , discriminated union , list , option и result . [52] Кортеж представляет собой набор из n значений, где n ≥ 0. Значение n называется арностью кортежа. 3-кортеж будет представлен как (A, B, C)
, где A, B и C — значения, возможно, разных типов. Кортеж может использоваться для хранения значений только тогда, когда количество значений известно во время проектирования и остается постоянным во время выполнения.
Запись — это тип, в котором элементы данных именуются. Вот пример определения записи:
тип R = { Имя : строка Возраст : целое }
Записи могут быть созданы как }. Ключевое слово используется для создания копии записи, как в }, что создает новую запись путем копирования и изменения значения поля (предполагая, что запись, созданная в последнем примере, была названа ).let r = { Name="AB"; Age=42
with
{ r with Name="CD"
r
Name
r
Тип дискриминируемого объединения — это типобезопасная версия объединений C. Например,
тип A = | UnionCaseX строки | UnionCaseY целого числа
Значения типа union могут соответствовать любому случаю union. Типы значений, переносимых каждым случаем union, включены в определение каждого случая.
Тип списка — это неизменяемый связанный список, представленный либо с помощью нотации ( — оператор cons ), либо в сокращенной форме как . Пустой список записывается . Тип параметра — это тип дискриминируемого объединения с вариантами выбора или . Типы F# могут быть универсальными , реализованными как универсальные типы .NET.head::tail
::
[item1; item2; item3]
[]
Some(x)
None
F# поддерживает лямбда-функции и замыкания . [52] Все функции в F# являются значениями первого класса и неизменяемы. [52] Функции могут быть каррированы . Будучи значениями первого класса, функции могут передаваться в качестве аргументов другим функциям. Как и другие функциональные языки программирования, F# допускает композицию функций с использованием операторов >>
и <<
.
F# обеспечиваетвыражения последовательности [53],которые определяют последовательностьseq { ... }
, список[ ... ]
или массив[| ... |]
через код, который генерирует значения. Например,
seq { for b in 0 .. 25 do if b < 15 then yield b * b }
формирует последовательность квадратов чисел от 0 до 14, отфильтровывая числа из диапазона чисел от 0 до 25. Последовательности являются генераторами — значения генерируются по требованию (т. е. вычисляются лениво ), в то время как списки и массивы вычисляются быстро.
F# использует сопоставление с образцом для привязки значений к именам. Сопоставление с образцом также используется при доступе к дискриминированным объединениям — объединение сопоставляет значение с правилами образца, и правило выбирается, когда сопоставление успешно. F# также поддерживает активные образцы как форму расширяемого сопоставления с образцом. [54] Он используется, например, когда существует несколько способов сопоставления по типу. [52]
F# поддерживает общий синтаксис для определения композиционных вычислений, называемыйВыражения вычислений . Выражения последовательностей, асинхронные вычисления и запросы являются особыми видами выражений вычислений. Выражения вычислений являются реализацией шаблонамонады.[53]
Поддержка F# для императивного программирования включает
for
петлиwhile
петли[| ... |]
синтаксисаdict [ ... ]
синтаксиса или System.Collections.Generic.Dictionary<_,_>
типа.Значения и поля записи также могут быть помечены как mutable
. Например:
// Определить 'x' с начальным значением '1' let mutable x = 1 // Изменить значение 'x' на '3' x <- 3
Кроме того, F# поддерживает доступ ко всем типам и объектам CLI, таким как те, которые определены в System.Collections.Generic
пространстве имен, определяющем императивные структуры данных.
Как и другие языки Common Language Infrastructure (CLI), F# может использовать типы CLI посредством объектно-ориентированного программирования. [52] Поддержка F# объектно-ориентированного программирования в выражениях включает:
x.Name
{ new obj() with member x.ToString() = "hello"
new Form()
x :? string
x :?> string
x.Method(someArgument=1)
new Form(Text="Hello")
x.Method(OptionalArgument=1)
Поддержка объектно-ориентированного программирования в шаблонах включает
:? string as s
Определения типов объектов F# могут быть определениями типов class, struct, interface, enum или delegate, соответствующими формам определений, найденным в C# . Например, вот класс с конструктором, принимающим имя и возраст и объявляющим два свойства.
/// Простое определение типа объекта type Person ( name : string , age : int ) = member x . Name = name member x . Age = age
F# поддерживает асинхронное программирование через асинхронные рабочие процессы . [55] Асинхронный рабочий процесс определяется как последовательность команд внутри async{ ... }
, как в
пусть asynctask = async { пусть req = WebRequest.Create ( url ) пусть ! response = req.GetResponseAsync ( ) используйте stream = response.GetResponseStream ( ) используйте streamreader = new System.IO.StreamReader ( stream ) return streamreader.ReadToEnd ( ) }
Указывает let!
, что выражение справа (получение ответа) должно быть выполнено асинхронно, но поток должен продолжаться только тогда, когда результат доступен. Другими словами, с точки зрения блока кода это как если бы получение ответа было блокирующим вызовом, тогда как с точки зрения системы поток не будет заблокирован и может использоваться для обработки других потоков, пока не станет доступен результат, необходимый для этого.
Асинхронный блок может быть вызван с помощью Async.RunSynchronously
функции. Несколько асинхронных блоков могут быть выполнены параллельно с помощью Async.Parallel
функции, которая принимает список async
объектов (в примере asynctask
это асинхронный объект) и создает другой асинхронный объект для параллельного выполнения задач в списках. Результирующий объект вызывается с помощью Async.RunSynchronously
. [55]
Инверсия управления в F# следует этой схеме. [55]
Начиная с версии 6.0, F# поддерживает создание, использование и возврат задач .NET напрямую. [56]
открыть System.Net.Http пусть fetchUrlAsync ( url : string ) = // string - > Task <string> задача { использовать client = new HttpClient ( ) пусть ! response = client.GetAsync ( url ) пусть ! content = response.Content.ReadAsStringAsync ( ) сделать ! Task.Delay 500 вернуть содержимое } // Использование let fetchPrint () = let task = task { let! data = fetchUrlAsync " https://example.com" printfn $ " {data}" } task.Wait ()
Параллельное программирование поддерживается частично посредством Async.Parallel
и Async.Start
других операций, которые запускают асинхронные блоки параллельно.
Параллельное программирование также поддерживается посредством Array.Parallel
операторов функционального программирования в стандартной библиотеке F#, прямого использования модели System.Threading.Tasks
программирования задач, прямого использования пула потоков .NET и потоков .NET, а также посредством динамической трансляции кода F# в альтернативные механизмы параллельного выполнения, такие как код GPU [9] .
Система типов F# поддерживает проверку единиц измерения для чисел. [57]
В F# вы можете назначать единицы измерения, такие как метры или килограммы, значениям с плавающей точкой, беззнаковым целым [58] и знаковым целым числам. Это позволяет компилятору проверять, что арифметика, включающая эти значения, является размерно согласованной, помогая предотвращать распространенные ошибки программирования, гарантируя, что, например, длины не будут ошибочно добавлены к времени.
Функция единиц измерения интегрируется с выводом типов F#, что требует минимальных аннотаций типов в пользовательском коде. [59]
[< Мера >] тип м // метр [< Мера >] тип с // секунда пусть расстояние = 100 . 0 < м > // float<m> пусть время = 5 . 0 < с > // float<s> пусть скорость = расстояние / время // float<m/s> [< Мера >] тип кг // килограмм [< Мера >] тип Н = ( кг * м )/( с ^ 2 ) // Ньютоны [< Мера >] тип Па = Н /( м ^ 2 ) // Паскали [< Мера >] тип дней пусть better_age = 3u < дни > // uint<дни>
Статическая проверка типов F# обеспечивает эту функциональность во время компиляции, но единицы стираются из скомпилированного кода. Следовательно, невозможно определить единицу значения во время выполнения.
F# допускает некоторые формы настройки синтаксиса посредством метапрограммирования для поддержки встраивания пользовательских доменно-специфичных языков в язык F#, в частности, посредством вычислительных выражений. [52]
F# включает функцию для метапрограммирования во время выполнения, называемую цитатами. [60] Выражение цитаты вычисляется в абстрактное синтаксическое дерево, представляющее выражения F#. Аналогично, определения, помеченные атрибутом, [<ReflectedDefinition>]
также могут быть доступны в их форме цитаты. Цитаты F# используются для различных целей, включая компиляцию кода F# в код JavaScript [8] и GPU [9] . Цитаты представляют свои выражения кода F# как данные для использования другими частями программы, при этом требуя, чтобы это был синтаксически правильный код F#.
F# 3.0 представил форму метапрограммирования времени компиляции через статически расширяемую генерацию типов, называемую поставщиками типов F#. [61] Поставщики типов F# позволяют компилятору и инструментам F# расширяться компонентами, которые предоставляют информацию о типах компилятору по требованию во время компиляции. Поставщики типов F# использовались для предоставления строго типизированного доступа к подключенным источникам информации масштабируемым способом, включая граф знаний Freebase . [62]
В F# 3.0 функции цитирования и вычислительных выражений F# объединены для реализации запросов LINQ . [63] Например:
// Используйте поставщик типов OData для создания типов, которые можно использовать для доступа к базе данных Northwind. open Microsoft.FSharp.Data.TypeProviders тип Northwind = ODataService < "http://services.odata.org/Northwind/Northwind.svc" > пусть db = Northwind . GetDataContext () // Выражение запроса. let query1 = query { for customer in db . Customers do select customer }
Сочетание поставщиков типов, запросов и строго типизированного функционального программирования известно как информационно-богатое программирование . [64]
F# поддерживает вариант модели программирования акторов посредством реализации в памяти легких асинхронных агентов. Например, следующий код определяет агента и отправляет 2 сообщения:
тип сообщения = | Постановка строки в очередь | Вывод AsyncReplyChannel из очереди < Option < string >> // Предоставляет одновременный доступ к списку строк let listManager = MailboxProcessor . Start ( fun inbox -> let rec messageLoop list = async { let ! msg = inbox . Receive () match msg with | Enqueue item -> return ! messageLoop ( item :: list ) | Вывести replyChannel -> список соответствия с | [] -> replyChannel . Ответить Нет return ! messageLoop список | head :: tail -> replyChannel . Ответить ( Некоторые head ) return ! messageLoop tail } // Запустить цикл с пустым списком messageLoop [] ) // Использование async { // Поставить в очередь несколько строк listManager.Post ( Поставить в очередь "Hello" ) listManager.Post ( Поставить в очередь " World " ) // Извлечь из очереди и обработать строки let! str = listManager.PostAndAsyncReply ( Dequeue ) str |> Option.iter ( printfn " Dequeued : %s" ) } | > Асинхронный .Старт
ИДЕ | Лицензия | Окна | линукс | macOS | Разработчик |
---|---|---|---|---|---|
Microsoft Visual Studio | Проприетарное (стандартное) Бесплатное ПО (общественная версия) | Да | Нет | Да | Майкрософт |
Код Visual Studio [66] | Проприетарная ( двоичный код ) Лицензия MIT ( исходный код ) | Да | Да | Да | Майкрософт |
Райдер [67] | Запатентованный | Да | Да | Да | JetBrains |
F# — язык программирования общего назначения .
SAFE Stack — это сквозной стек F# для разработки веб-приложений. Он использует ASP.NET Core на стороне сервера и Fable на стороне клиента. [68]
Альтернативным сквозным вариантом F# является фреймворк WebSharper . [69]
F# можно использовать вместе с Visual Studio Tools for Xamarin для разработки приложений для iOS и Android . Библиотека Fabulous обеспечивает более удобный функциональный интерфейс.
Среди прочего, F# используется для количественного финансового программирования, [70] торговли энергоносителями и оптимизации портфеля, [71] машинного обучения, [72] бизнес-аналитики [73] и социальных игр на Facebook . [74]
В 2010-х годах F# позиционировался как оптимизированная альтернатива C# . Возможность написания скриптов на F# и межъязыковая совместимость со всеми продуктами Microsoft сделали его популярным среди разработчиков. [75]
F# можно использовать в качестве языка сценариев, в основном для сценариев цикла чтения-вычисления-печати (REPL) для настольных систем. [76]
Сообщество F# с открытым исходным кодом включает F# Software Foundation [10] и F# Open Source Group на GitHub . [11] Популярные проекты F# с открытым исходным кодом включают:
В F# реализован устаревший «режим совместимости с ML», который позволяет напрямую компилировать программы, написанные на большом подмножестве OCaml, без функторов, объектов, полиморфных вариантов или других дополнений.
Ниже приведено несколько небольших примеров:
// Это комментарий к примеру программы Hello World. printfn "Hello World!"
Определение типа записи. Записи по умолчанию неизменяемы и сравниваются по структурному равенству.
тип Человек = { Имя : строка Фамилия : строка Возраст : целое } // Создание экземпляра записи let person = { FirstName = "John" ; LastName = "Doe" ; Age = 30 }
Класс Person с конструктором, принимающим имя и возраст, а также два неизменяемых свойства.
/// Это комментарий к документации для определения типа. type Person ( name : string , age : int ) = member x . Name = name member x . Age = age /// создание экземпляра класса let mrSmith = Person ( "Smith" , 42 )
Простым примером, который часто используется для демонстрации синтаксиса функциональных языков, является функция факториала для неотрицательных 32-битных целых чисел, показанная здесь на F#:
/// Используя выражение сопоставления с образцом, пусть rec factorial n = match n with | 0 -> 1 | _ -> n * factorial ( n - 1 ) /// Для функций с одним аргументом есть синтаксический сахар (функция сопоставления с образцом): let rec factorial = function | 0 -> 1 | n -> n * factorial ( n - 1 ) /// Использование оператора свертывания и диапазона let factorial n = [ 1 .. n ] |> Seq . fold (*) 1
Примеры итераций:
/// Итерация с использованием цикла 'for' let printList lst = for x in lst do printfn $ "{x}" /// Итерация с использованием функции высшего порядка let printList2 lst = List . iter ( printfn "%d" ) lst /// Итерация с использованием рекурсивной функции и сопоставления с образцом let rec printList3 lst = match lst with | [] -> () | h :: t -> printfn "%d" h printList3 t
Примеры Фибоначчи:
/// Формула числа Фибоначчи [< TailCall >] пусть fib n = пусть rec g n f0 f1 = сопоставить n с | 0 -> f0 | 1 -> f1 | _ -> g ( n - 1 ) f1 ( f0 + f1 ) g n 0 1 /// Другой подход - ленивая бесконечная последовательность чисел Фибоначчи let fibSeq = Seq . unfold ( fun ( a , b ) -> Some ( a + b , ( b , a + b ))) ( 0 , 1 ) // Печать четных чисел fibs [ 1 .. 10 ] |> Список . map fib |> Список . filter ( fun n -> ( n % 2 ) = 0 ) |> printList // То же самое, используя выражение списка [ for i in 1 .. 10 do let r = fib i if r % 2 = 0 then yield r ] |> printList
Пример программы Windows Forms:
// Открываем библиотеку Windows Forms open System.Windows.Forms // Создаем окно и задаем несколько свойств let form = new Form ( Visible = true , TopMost = true , Text = "Welcome to F#" ) // Создаем метку для отображения текста в форме let label = let x = 3 + ( 4 * 5 ) new Label ( Text = $ "{x}" ) // Добавляем метку к форме form.Controls.Add ( label )// Наконец, запустите форму [< System . STAThread >] Application . Run ( form )
Пример асинхронного параллельного программирования (параллельные задачи ЦП и ввода-вывода):
/// Простой детектор простых чисел let isPrime ( n : int ) = let bound = int ( sqrt ( floatn ) ) seq { 2 ..bound } |> Seq .forall ( fun x - > n % x < > 0 ) // Мы используем асинхронные рабочие процессы let primeAsync n = async { return ( n , isPrime n ) } /// Возвращаем простые числа от m до n, используя несколько потоков let primes m n = seq { m .. n } |> Seq . map primeAsync |> Async . Parallel |> Async . RunSynchronously |> Array . filter snd |> Array . map fst // Запустить тест простых чисел 1000000 1002000 |> Array . iter ( printfn "%d" )
{{cite web}}
: Отсутствует или пусто |title=
( помощь )[F#] основан на архитектуре Core ML и, в частности, имеет базовый язык, в значительной степени совместимый с языком OCaml