Учебник F# для начинающих
F# — функциональный-first язык на платформе .NET: прагматичный потомок ML, который сочетает строгую статическую типизацию с лаконичностью и почти полным отсутствием шаблонного кода. В этом курсе вы освоите идеи функционального программирования на практике — неизменяемость по умолчанию, мощный вывод типов, каррирование и оператор конвейера, сопоставление с образцом, алгебраические типы данных и моделирование домена, безопасную работу с option и Result, асинхронность, а также уникальные фишки F#: единицы измерения, активные шаблоны и type providers.
Курс опирается на ваше знакомство с .NET и сравнивает F# с C# (когда функциональный стиль выгоднее) и с Haskell (прагматизм против чистоты). Код на F# в браузере не исполняется, поэтому примеры сопровождаются точным выводом. К концу курса вы будете писать идиоматичный F# и понимать, почему его выбирают в финансах, в моделировании сложных доменов и в data science.
Курс «F#: функциональное программирование на .NET» состоит из 6 разделов и 21 урока: Знакомство с F# и первые шаги, Типы, функции и конвейеры, Сопоставление с образцом, Алгебраические типы и моделирование домена, Коллекции, рекурсия и обработка ошибок и Асинхронность, .NET и продвинутые возможности. Уроки идут по порядку — от основ к более сложным темам, в каждом есть объяснение с примерами, а в конце — вопросы для самопроверки. К урокам привязаны задачи с автоматической проверкой: прочитали тему — сразу закрепили её кодом.
Программа курса
1 Знакомство с F# и первые шаги
- Что такое F# и зачем он нужен
F# — функциональный-first язык на .NET: прагматичный ML, лаконичность, статическая типизация и где его применяют на практике.
- Установка: .NET SDK, dotnet fsi и скрипты .fsx
Ставим .NET SDK, запускаем F# Interactive (dotnet fsi), пишем и исполняем скрипты .fsx — рабочее окружение для курса.
- Значения и неизменяемость: let и иммутабельность по умолчанию
let создаёт неизменяемые значения, mutable — исключение. Почему иммутабельность по умолчанию делает код предсказуемым.
- Что такое F# и зачем он нужен
2 Типы, функции и конвейеры
- Вывод типов: статика без аннотаций
Мощный вывод типов в F#: статическая типизация почти без аннотаций, как работает алгоритм и когда тип нужно указать явно.
- Функции, каррирование и частичное применение
Функции в F# каррированы по умолчанию: что это даёт, как работает частичное применение и почему функции — значения.
- Конвейер |> и композиция >>
Оператор конвейера |> и композиция функций >> в F#: как строить читаемые цепочки преобразований данных.
- Базовые типы и кортежи
Базовые типы F# (int, float, bool, string, char, unit) и кортежи для группировки значений без объявления классов.
- Вывод типов: статика без аннотаций
3 Сопоставление с образцом
- match: основы сопоставления
Выражение match в F#: как сопоставлять значения с образцами, почему это выражение, а не оператор, и зачем нужна исчерпывающность.
- Разбор структур: списки, кортежи, вложенность
Деструктуризация в pattern matching: разбор кортежей, списков (head::tail), вложенных структур и привязка имён.
- Активные шаблоны (active patterns)
Активные шаблоны F#: расширяем сопоставление с образцом собственной логикой разбора, частичные и параметризованные паттерны.
- match: основы сопоставления
4 Алгебраические типы и моделирование домена
- Записи (records)
Записи в F#: именованные неизменяемые структуры данных, копирование с изменением через with, структурное равенство.
- Размеченные объединения (discriminated unions)
Размеченные объединения F#: тип-сумма с несколькими вариантами, моделирование выбора, разбор через match.
- option вместо null: безопасность по типам
Тип option в F#: Some/None вместо null, безопасная работа с отсутствующими значениями, map и defaultValue.
- Невозможные состояния — непредставимы
Главный принцип моделирования домена в F#: проектируем типы так, чтобы недопустимые состояния нельзя было даже создать.
- Записи (records)
5 Коллекции, рекурсия и обработка ошибок
- Коллекции и их обработка: списки, массивы, seq, map/filter/fold
Три коллекции F# (список, массив, seq) и ключевые функции их обработки: map, filter, fold в функциональном конвейере.
- Рекурсия и хвостовая рекурсия
Рекурсия в F# через rec, почему обычная рекурсия рискует переполнить стек и как хвостовая рекурсия это решает.
- Обработка ошибок: Result и railway-oriented programming
Тип Result в F#: Ok/Error вместо исключений, цепочки вычислений и railway-oriented programming для безопасной обработки ошибок.
- Коллекции и их обработка: списки, массивы, seq, map/filter/fold
6 Асинхронность, .NET и продвинутые возможности
- Асинхронность: async
Асинхронность в F# через async и вычислительные выражения: let!, неблокирующие операции и запуск асинхронных задач.
- ООП и взаимодействие с .NET
F# умеет в ООП: классы, интерфейсы, члены типов и прямой доступ к библиотекам C# и всей экосистеме .NET.
- Уникальные фишки: единицы измерения и type providers
Две уникальные возможности F#: единицы измерения (units of measure) и type providers — типобезопасность величин и доступа к данным.
- F# против C# и Haskell: когда что выбрать
Сравнение F# с C# (когда функциональный стиль выгоднее) и с Haskell (прагматизм против чистоты), области применения F#.
- Асинхронность: async