Языки программирования

Учебник OCaml для начинающих

25 уроков · 8 разделов · бесплатно, без регистрации

OCaml — функциональный язык семейства ML, на котором пишут торговые системы Jane Street, компиляторы и системы верификации. Этот курс ведёт от установки и базовых выражений к сильному выводу типов, сопоставлению с образцом, алгебраическим типам и мощнейшей в индустрии системе модулей и функторов. По пути мы проводим параллели с Haskell, F# и Scala и показываем, чем OCaml прагматичнее: энергичные вычисления, разрешённая мутация и компиляция в быстрый нативный код.

Курс «OCaml: практичный функциональный язык» состоит из 8 разделов и 25 уроков: Знакомство с OCaml, Типы и вывод типов, Функции, Данные: кортежи, записи, варианты, Сопоставление с образцом, Списки, полиморфизм, ошибки, Модули и функторы и Прагматизм: изменяемость, ООП, производительность. Уроки идут по порядку — от основ к более сложным темам, в каждом есть объяснение с примерами, а в конце — вопросы для самопроверки. К урокам привязаны задачи с автоматической проверкой: прочитали тему — сразу закрепили её кодом.

Программа курса

  1. 1 Знакомство с OCaml

    1. Что такое OCaml и зачем он нужен

      OCaml — прагматичный функциональный язык семейства ML: статическая типизация с выводом типов, скорость нативного кода, мультипарадигменность.

    2. Установка: opam, dune и REPL utop

      Ставим OCaml через opam, знакомимся со сборщиком dune и интерактивным REPL utop для экспериментов с кодом.

    3. Всё — выражение: let и значения

      В OCaml почти всё является выражением, возвращающим значение. Разбираем let-связывания, локальные let ... in и отличие от переменных.

  2. 2 Типы и вывод типов

    1. Сильный вывод типов: Хиндли — Милнер

      Алгоритм Хиндли — Милнера выводит типы без аннотаций. Как компилятор OCaml угадывает самый общий тип каждого выражения и почему это безопасно.

    2. Базовые типы: int, float и раздельная арифметика

      int и float в OCaml — разные типы с разными операторами: + и +., * и *.. Зачем это сделано и как избежать ошибок арифметики.

    3. Строки, символы, логика и unit

      Работа со строками (^, индексация), символами char, логическими операторами && и ||, и роль типа unit.

  3. 3 Функции

    1. Функции, каррирование и частичное применение

      Функции в OCaml каррированы: каждая принимает один аргумент и возвращает функцию. Это даёт элегантное частичное применение.

    2. Конвейер |> и композиция функций

      Оператор |> передаёт значение в функцию слева направо, делая код читаемым как цепочку преобразований. Композиция и оператор @@.

    3. Рекурсия: let rec и хвостовые вызовы

      Рекурсивные функции требуют ключевого слова rec. Обычная и хвостовая рекурсия, аккумуляторы и почему хвостовая рекурсия не переполняет стек.

  4. 4 Данные: кортежи, записи, варианты

    1. Кортежи и записи

      Кортежи группируют значения по позиции, записи (records) — по именованным полям. Создание, доступ к полям и неизменяемость.

    2. Алгебраические типы: моделируем домен

      Вариантные типы (sum types) позволяют точно описать множество состояний домена. Конструкторы с данными и сила исчерпывающего моделирования.

    3. option вместо null

      Тип option (Some/None) делает отсутствие значения явным в системе типов, устраняя целый класс ошибок NullPointerException.

  5. 5 Сопоставление с образцом

    1. match: основы сопоставления с образцом

      Сопоставление с образцом match — центральная конструкция OCaml. Синтаксис, разбор вариантов, кортежей и связывание переменных.

    2. Исчерпывающность и сторожевые условия when

      Компилятор проверяет, что match покрывает все случаи. Предупреждения об исчерпывающности, охранные условия when и образцы с |.

  6. 6 Списки, полиморфизм, ошибки

    1. Списки и модуль List

      Списки — фундаментальная структура OCaml. Устройство (head/tail), конструктор ::, рекурсивная обработка и ключевые функции List.

    2. map, filter и fold

      Три кита обработки коллекций: map преобразует, filter отбирает, fold сворачивает в одно значение. fold_left и fold_right.

    3. Параметрический полиморфизм

      Полиморфные функции работают с любым типом через переменные типа 'a. Параметрический полиморфизм и принцип параметричности.

    4. Обработка ошибок: result против исключений

      OCaml предлагает два пути обработки ошибок: тип result для ожидаемых сбоев и исключения для исключительных ситуаций.

  7. 7 Модули и функторы

    1. Модули и сигнатуры

      Модули группируют типы и функции, сигнатуры задают интерфейс и скрывают детали реализации. module, struct/sig и инкапсуляция.

    2. Функторы: модули, параметризованные модулями

      Функтор — это функция от модуля к модулю. Как параметризовать модуль другим модулем (множества, сортировка) и зачем это нужно.

    3. Организация проекта и экосистема dune

      Как устроен реальный OCaml-проект: файлы .ml/.mli, библиотеки и исполняемые файлы в dune, подключение пакетов через opam, тестирование.

  8. 8 Прагматизм: изменяемость, ООП, производительность

    1. Изменяемость: ref, mutable и массивы

      OCaml прагматичен: когда нужна мутация, есть ref-ячейки, mutable-поля записей и массивы с быстрым доступом по индексу.

    2. Императивные конструкции: for, while, побочные эффекты

      Циклы for и while, последовательность действий через ; и печать. Когда императивный стиль в OCaml уместнее рекурсии.

    3. ООП в OCaml: классы и объекты

      В OCaml есть полноценная объектная система: классы, объекты, наследование и структурная типизация. Почему она используется редко.

    4. Производительность, компиляция и место OCaml

      Нативная компиляция, сборщик мусора и итоговое сравнение OCaml с Haskell, F# и Scala. Где OCaml — лучший выбор.