Сила OCaml. Разбираемся с типизацией и пишем скрипты

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

OCaml и семейство ML

OCaml относится к семейству языков ML. К нему же относятся ныне редкий Standard ML, Microsoft F#, который во многом представляет собой клон OCaml, и, с оговорками, Haskell.

Многие языки семейства ML способны производить статическую проверку типов в коде, где нет ни одного объявления типа переменной благодаря механизму вывода типов. Ограниченную форму вывода типов многие уже видели в Go, где можно не объявлять примитивные типы, а просто писать var x = 10. Swift предоставляет те же возможности. OCaml идет гораздо дальше и выводит типы функций.

let sqr x = x * x (* sqr : int -> int *)

Теоретическая основа вывода типов — алгоритм Хиндли — Милнера. Детерминированный вывод типов возможен не во всех системах. В частности, Haskell использует тот же подход, но функции в нем требуют явного объявления типа. Цена детерминированности — отсутствие полиморфизма ad hoc (перегрузки функций). Каждая функция в OCaml может иметь один и только один тип. Отсутствие перегрузки функций компенсируется «функторами» — параметризованными модулями.

Swift заимствовал многие концепции из ML, в частности алгебраические типы и параметрический полиморфизм, которые обеспечивают удобную и безопасную работу функций с коллекциями (списками) независимо от типа значений. Новые языки для JS также зачастую заимствуют из них, так что знакомство с ML полезно для их понимания.

Почему OCaml?

Традиционное применение OCaml и языков семейства ML — разработка компиляторов, средств статического анализа и автоматического доказательства теорем. К примеру, на нем был написан компилятор Rust до того, как он научился компилировать сам себя. OCaml также нашел применение в финансовой сфере, где ошибка в коде может за пару минут довести компанию до банкротства, например в Lexifi и Jane Street.

Пригодным к применению в качестве скриптового его делает особенность реализации: он предоставляет одновременно интерпретатор, компилятор в байт-код и компилятор в машинный код для популярных платформ, в том числе x86 и ARM. Можно начать разработку в интерактивной оболочке интерпретатора, затем записать код в файл. А если скрипт превращается в полноценную программу, скомпилировать ее в машинный код.

INFO

С помощью сторонних инструментов вроде js_of_ocaml и BuckleScript код на OCaml также можно компилировать в JavaScript. В Facebook таким способом переписали большую часть Facebook Messenger на ReasonML, это альтернативный синтаксис для OCaml.

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

Мы не будем затрагивать веб-скрипты и сосредоточимся на традиционных. В этой статье я также намеренно опускаю создание собственных типов, систему модулей и многие другие возможности. Первая цель — показать «вкус» языка.

INFO

В этой статье предполагается использование совместимой с POSIX системы: Linux, FreeBSD или macOS. Сам OCaml работает на Windows, но менеджер пакетов OPAM пока не поддерживает эту систему, поэтому библиотеки пришлось бы собирать вручную со всеми зависимостями. Теоретически использовать OPAM можно в Cygwin, но я не пробовал.

Установка

Стандартным менеджером пакетов для OCaml стал OPAM. Он может устанавливать сам компилятор, библиотеки и переключаться между разными версиями. Многие системы предоставляют какую-то версию OCaml в репозиториях (часто устаревшую), но с помощью OPAM легко поставить самую свежую от имени обычного пользователя. Для Linux и macOS авторы предоставляют статически скомпилированную версию.

WWW

Как установить OPAM, ты можешь прочитать в документации.

После установки мы поставим самую новую на настоящий момент версию компилятора 4.07 и несколько утилит и библиотек, которые потребуются нам в примерах.

$ opam switch 4.05
$ opam install utop lambdasoup

Для проверки работоспособности запустим utop — интерактивную оболочку интерпретатора. Стандартный интерпретатор (ocaml) слишком «спартанский» — без поддержки истории команд и автодополнения, поэтому его мы будем использовать только в неинтерактивном режиме.

$ utop

utop # print_endline "hello world" ;;
hello world
- : unit = ()

Интерактивный интерпретатор позволяет вводить многострочные выражения, но из-за этого для завершения ввода нужно применять символ ;;. Использовать его в исходном коде допустимо, но излишне.

INFO

Компилятор в байт-код называется ocamlc, а нативный компилятор — ocamlopt. Сегодня мы столкнемся с ocamlc, но рассматривать компиляцию не будем.

Продолжение доступно только участникам

Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», увеличит личную накопительную скидку и позволит накапливать профессиональный рейтинг Xakep Score! Подробнее

Вариант 2. Открой один материал

Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.


Даниил Батурин: Координатор проекта VyOS (https://vyos.io), «языковед», функциональщик, иногда сетевой администратор

Комментарии (1)