F Sharp
| F# | |
|---|---|
| | |
| Класс языка |
мультипарадигменный: функциональное, объектно-ориентированное, обобщённое, императивное программирование |
| Появился в | 2005 |
| Автор | Microsoft Research |
| Разработчик | Microsoft и F Sharp Software Foundation[вд] |
| Расширение файлов |
.fs, .fsi, .fsx или .fsscript |
| Выпуск | 10.0 (11 ноября 2025) |
| Система типов | строгая, статическая / динамическая |
| Испытал влияние | Objective Caml, C#, Haskell |
| Лицензия | Apache Software License |
| Сайт | fsharp.org |
| ОС | Кроссплатформенное программное обеспечение (.NET Framework, Mono) |
F# (произносится эф-шарп) — мультипарадигмальный язык программирования из семейства языков .NET, поддерживающий функциональное программирование в дополнение к императивному (процедурному) и объектно-ориентированному программированию. Структура F# во многом схожа со структурой OCaml с той лишь разницей, что F# реализован поверх библиотек и среды исполнения .NET. Язык был разработан Доном Саймом (англ. Don Syme) в Microsoft Research в Кембридже, в настоящее время его разработку ведёт Microsoft Developer Division. F# достаточно тесно интегрируется со средой разработки Visual Studio и включён в поставку Visual Studio 2010/2012/2013/2015/2017/2019/2022/2026; разработаны также компиляторы для Mac и Linux[1].
Microsoft интегрировала среду разработки F# в Visual Studio 2010 и более новые версии.
4 ноября 2010 года код компилятора F# и основных библиотек к нему опубликован под Apache License 2.0[2].
Особенности
Код на языке F# является безопасным в отношении типов, часто бывает более компактным, чем аналогичный код C#, за счёт вывода типов. В F# действует строгая типизация, неявные преобразования типов полностью отсутствуют, что полностью исключает ошибки, связанные с приведением типов.
Такие возможности, как обобщённое программирование и функции высших порядков позволяют писать абстрактные обобщённые алгоритмы, которые управляют параметризованными структурами данных (например, массивами, списками, графами, деревьями).
Во многих языках большинство значений являются переменными. Например, в результате исполнения следующего кода на языке C в переменной x будет храниться значение 3:
int x = 2;
x++;
В F#, напротив, по умолчанию все значения являются константами. F# допускает переменные, для чего требуется специально помечать значения как изменяемые при помощи слова mutable:
let x = 2 // неизменяемое значение
let mutable y = 2 // переменная
x <- 3 // ошибка
y <- 3 // Ok. y = 3
Также в F# есть ссылочные типы и объекты, которые также могут содержать изменяемые значения. Тем не менее, бо́льшая часть кода является чистыми функциями, что позволяет избежать многих ошибок и упростить отладку. Кроме того, упрощается распараллеливание программ. При всём этом код редко становится сложнее, чем аналогичный код на императивном языке.
Одна из основных идей F# заключается в том, чтобы удостовериться, что имеющийся код и типы в функциональном языке программирования могут быть легко доступны из других .NET-языков. Программы на F# компилируются в сборки CLR (файлы с расширениями .exe и .dll), однако, для их запуска необходима установка пакета среды исполнения дополнительно к .NET Framework.
Интересной особенностью (и отличием от OCaml) является управление логической вложенностью конструкций кода за счёт отступов в виде произвольного количества пробелов (и только лишь пробелов). Знаки табуляции для этой цели не поддерживаются. Это приводит к постоянным дискуссиям на форумах опытных разработчиков, которые привыкли пользоваться знаками табуляции в других языках программирования.
Компилятор и интерпретатор
F# — компилируемый язык программирования, при этом в качестве промежуточного языка используется язык Common Intermediate Language (CIL), так же как и в программах, написанных на языках C# или VB.NET.
Наряду с F#-компилятором (fsc) присутствует и F#-интерпретатор (fsi), который исполняет F#-код интерактивно.
Отличительной чертой F#-компилятора и F#-интерпретатора является возможность воспринимать код двумя разными способами — немедленно (по умолчанию) и отложенно (программисту требуется явно указать это в исходном коде). В случае немедленной интерпретации, выражения вычисляются заранее в момент запуска программы на выполнение, независимо от того, вызываются ли они в процессе выполнения программы или нет. В этом случае, зачастую снижается производительность выполнения программы, а также происходит неэкономное расходование ресурсов системы (например, памяти). В случае ленивой интерпретации кода, выражения вычисляются только в тот момент, когда к ним происходит непосредственное обращение в процессе выполнения программы. Это избавляет программу от перечисленных выше недостатков, но снижает предсказуемость в плане объёма и последовательности использования ресурсов (процессорного времени, памяти, устройств ввода-вывода и т. п.) на различных этапах выполнения программы.
Примеры
Синтаксис F# построен на математической нотации, а программирование чем-то похоже на алгебру, что делает F# похожим на Haskell. Например, когда вы определяете новый тип, то можете указать, что переменными этого типа будут «целые или строки». Вот как это выглядит:
type myType = IntVal of int | StringVal of string
Важным примером таких типов является Option, который содержит либо значение некоторого типа, либо ничего.
type Option<a> = None | Some of a
Он является стандартным типом F# и часто используется в ситуациях, когда результатом работы какого-то кода (например, поиска в структуре данных) является значение, которое может и не быть получено.
Код также представляет собой математическую нотацию. Следующая конструкция эквивалентна f(x) = x + 1 в алгебре:
let f x = x + 1
F# работает следующим образом: тип «f» представляет собой «int -> int», то есть функция получает на вход целое и выдаёт на выход целое.
F# позволяет получить доступ абсолютно ко всему, что есть в FCL. Синтаксис для работы с библиотеками .NET в этом смысле максимально близок к синтаксису C#. Особенности языка заметны при использовании всего спектра возможностей F#. К примеру, следующий код применяет функцию к элементам списка:
let rec map func lst =
match lst with
| [] -> []
| head :: tail -> func head :: map func tail
let myList = [1;3;5]
let newList = map (fun x -> x + 1) myList
В «newList» теперь находится «[2;4;6]».
Разбор списка в этой функции ведётся с помощью ещё одной мощной возможности сопоставления с образцом. Она позволяет задавать образцы при совпадении с которыми вычисляются соответствующие вхождения оператора match. Первый образец «[]» означает пустой список. Второй — список состоящий из первого элемента и хвоста (который может быть произвольным списком, в том числе и пустым). Во втором образце значение головы связывается с переменной head, а хвоста с tail (имена могут быть произвольные). Таким образом кроме основной задачи образец ещё позволяет производить декомпозицию сложных структур данных. Например, в случае с типом Option сопоставление с образцом выглядит так:
match x with
| Some v -> printfn "Найдено значение %d." v
| None -> printfn "Ничего не найдено."
| _ -> printfn "Привет"
Язык поддерживает генераторные выражения, определенные для множеств { … }, списков [ … ] и массивов [| … |]
Например:
let test n = [ for i in 0 .. n do
if i % 2 = 0 then
yield i ]
Функция map является одной из стандартных функций над списками, которые содержатся в модуле List. Также существуют функции для других структур данных, объявленные в модулях Array, Set, Option.
Полезным инструментом является оператор pipe-forward (|>), который позволяет писать цепочки вызовов функций в обратном порядке. В результате имеет место такой код (в комментариях указаны промежуточные значения):
[1; 2; 5]
|> List.map ((+) 1) // [2; 3; 6]
|> List.filter (fun x -> x % 2 = 0) // [2; 6]
|> List.sum // 8
Использование оператора |> исключает необходимость использования большого числа скобок, а также изменяет визуальное восприятие кода. И теперь данный код читается так: взять такой-то список, прибавить к каждому элементу 1, затем оставить только четные элементы, вернуть их сумму. То есть, описывается последовательность действий, выполняемая над изначальным объектом, в том порядке, в котором она происходит и на компьютере.
Далее небольшая демонстрация того, насколько функции .NET расширяют возможности F#. Одним из примеров являются оконные приложения и событийная обработка. Событийная обработка означает — какие-то действия в программе происходят только как реакция на определенные события — действия пользователей, подключение устройств и т. д. Проект можно создать как в Visual Studio, так и в любом текстовом документе, который затем подается на вход компилятору F# (fsc).
// open - подключение модулей и пространств имен для использования содержащихся в них
// значений, классов и других модулей.
open System.Windows.Forms // - классы Form (окно), Button (кнопка)и т. д.
// Beep - звуковой сигнал
// В качестве аргументов beep передаются еще некоторые параметры, которые мы не используем
let beep _ = System.Console.Beep()
// создание окна с программным именем окно !необходимо вызывать слово-функцию отображения - к примеру Application.Run(окно)!
// Visible - булевское значение, является ли окно видимым
// TopMost - отображается ли окно на переднем плане (очерёдность окон с одинаковым значением в обратном порядке вызова)
// Text - текст заголовка окна
let window = new Form(Visible=true,TopMost=true,Text="",
Top = 0, Left = 0, Height = 512, Width = 768)
window.WindowState <- FormWindowState.Normal // Нормальное (, Свёрнутое, Развёрнутое) окно. Просто для примера не внесено в конструктор
window.ClientSizeChanged.Add beep
window.KeyDown.Add beep
window.KeyPress.Add beep
window.KeyUp.Add beep
Application.Run window // отображение окна
Факториал
Рекурсивная функция вычисления факториала нативным способом:
let rec fac n =
if n < 2 then 1
else n * fac(n - 1)
Рекурсивная функция вычисления факториала, оптимизированная под хвостовую рекурсию.
let factorial num =
let rec fac num acc =
match num with
|x when x < 2 -> acc
|_ -> fac (num - 1) (acc * num)
fac num 1
Функция вычисления факториала, в императивном стиле с использованием изменяемого состояния.
let factorial num =
if num < 2 then 1
else
let mutable fac = 1
for i in [2..num] do
fac <- fac * i
fac
Функция вычисления факториала с использованием свертки списка и каррированой операции умножения:
let fac n = List.fold (*) 1 [1..n]
Рекурсивная функция вычисления чисел Фибоначчи с использованием метода сопоставления с образцом:
let rec fib n a b =
match n with
| 0 -> a
| 1 -> b
| _ -> fib (n - 1) b (a + b)
Примечания
- ↑ Ссылки для загрузки F# на сайте Microsoft Research. Дата обращения: 24 июня 2011. Архивировано 24 июня 2011 года.
- ↑ Announcing the F# Compiler + Library Source Code Drop. Дата обращения: 5 ноября 2010. Архивировано 17 января 2013 года.
См. также
Ссылки
- F# (англ.) — Microsoft F# Developer Center.
- Введение в F#. Евгений Лазин, Максим Моисеев, Давид Сорокин, «Практика функционального программирования», 2010, № 5
- Введение в F# — интервью с Доном Саймом.
- Обсуждение книги по F# на русском языке Дона Сайма «The Definitive Guide to F#»
- Три парадигмы F# — Хабрахабр.
- Try F# Tutorials — Ознакомление с языком F#. программирования
Литература
- Крис Смит (Smith, Chris). Программирование на F# = Programming F#. — O'Reilly, 2011. — 448 с. — ISBN 978-5-93286-199-8.
- Дмитрий Сошников. Функциональное программирование на F#. — Москва: ДМК Пресс, 2011. — 192 с. — ISBN 978-5-94074-689-8.
- Syme, Don; Granicz, Adam; Cisternino, Antonio. Expert F# (англ.). — Apress, 2007.
Content Disclaimer
Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.
- The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
- There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
- It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
- Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
- Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.