OCaml - Википедия - OCaml

OCaml
OCaml Logo.svg
ПарадигмаМультипарадигма: функциональный, императив, модульный,[1] объектно-ориентированный
СемьяML
РазработаноКсавье Леруа, Жером Вуйон, Дэмиен Долигес, Дидье Реми, Аскандер Суарес
РазработчикINRIA
Впервые появился1996; 24 года назад (1996)
Стабильный выпуск
4.11.0 / 19 августа 2020 г.; 3 месяца назад (2020-08-19)[2]
Печатная дисциплинаПредполагаемый, статический, сильный, структурный
Язык реализацииOCaml, C
ПлатформаIA-32, x86-64, Мощность, SPARC, АРМ 32-64
Операционные системыКроссплатформенность: Unix, macOS, Windows
ЛицензияLGPLv2.1
Расширения имени файла.ml, .mli
Интернет сайтOcaml.org
Под влиянием
C, Caml, Модула-3, Паскаль, Стандартный ML
Под влиянием
АТС, Coq, Вяз, F #, F *, Haxe, Опа, Ржавчина, Scala

OCaml (/ˈkæмəl/ ой-КАМ-əl, ранее Цель Caml) это общее назначение, язык программирования с несколькими парадигмами что расширяет Caml диалект ML с объектно-ориентированный Особенности. OCaml был создан в 1996 году Ксавье Леруа, Жером Вуйон, Дэмиен Долигес, Дидье Реми, Аскандер Суарес, и другие.

OCaml набор инструментов включает интерактивный верхний уровень устный переводчик, а байт-код компилятор, оптимизирующий собственный код компилятор, обратимый отладчик и диспетчер пакетов (OPAM). OCaml изначально разрабатывался в контексте автоматическое доказательство теорем, и имеет большое присутствие в статический анализ и формальные методы программного обеспечения. Помимо этих областей, он нашел серьезное применение в системное программирование, Веб-разработка, и финансовое проектирование, среди других областей приложений.

Акроним CAML первоначально обозначал Категориальный абстрактный машинный язык, но OCaml опускает это абстрактная машина.[3] OCaml - это бесплатное программное обеспечение с открытым исходным кодом проект управляется и в основном поддерживается Французский институт исследований в области компьютерных наук и автоматизации (INRIA). В начале 2000-х годов элементы OCaml были приняты многими языками, в частности F # и Scala.

Философия

ML -производные языки известны своими статическими системы типов и определение типа компиляторы. OCaml объединяет функциональный, императив, и объектно-ориентированного программирования под системой типа ML. Таким образом, программистам не нужно хорошо знать парадигму чисто функционального языка, чтобы использовать OCaml.

Требуя от программиста работы в рамках ограничений своей системы статических типов, OCaml устраняет многие связанные с типами проблемы времени выполнения, связанные с динамически типизированными языками. Кроме того, компилятор определения типа OCaml значительно снижает потребность в ручных аннотациях типов, которые требуются для большинства языков со статической типизацией. Например, тип данных переменных и сигнатуры функций обычно не нужно объявлять явно, как в таких языках, как Ява и C #, потому что они могут быть выведены из операторов и других функций, которые применяются к переменным и другим значениям в коде. Эффективное использование системы типов OCaml может потребовать некоторой сложности от программиста, но эта дисциплина вознаграждается надежным и высокопроизводительным программным обеспечением.

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

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

Ксавье Леруа заявил, что «OCaml обеспечивает не менее 50% производительности достойного компилятора C»,[4] хотя прямое сравнение невозможно. Некоторые функции в стандартной библиотеке OCaml реализованы с помощью более быстрых алгоритмов, чем эквивалентные функции в стандартных библиотеках других языков. Например, реализация объединения наборов в стандартной библиотеке OCaml в теории асимптотически быстрее, чем эквивалентная функция в стандартных библиотеках императивных языков (например, C ++, Java), потому что реализация OCaml использует неизменность наборов для повторного использования частей ввода. устанавливает на выходе (см. постоянная структура данных ).

Функции

OCaml имеет статический система типов, вывод типа, параметрический полиморфизм, хвостовая рекурсия, сопоставление с образцом, первоклассная лексическая закрытие, функторы (параметрические модули), Обработка исключений, и добавочное поколение автоматический сбор мусора.

OCaml отличается расширением вывода типов в стиле ML на объектную систему в языке общего назначения. Это позволяет структурное подразделение, где типы объектов совместимы, если их сигнатуры методов совместимы, независимо от их объявленного наследования (необычная функция в статически типизированных языках).

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

Дистрибутив OCaml содержит:

Компилятор машинного кода доступен для многих платформ, в том числе Unix, Майкрософт Виндоус, и яблоко macOS. Переносимость достигается за счет встроенного генерация кода поддержка основных архитектур: IA-32, X86-64 (AMD64), Мощность, SPARC, РУКА, и ARM64.[5]

Байт-код OCaml и программы с машинным кодом могут быть написаны на многопоточный стиль с упреждающим переключением контекста. Однако, поскольку сборщик мусора системы INRIA OCaml (который является единственной доступной в настоящее время полной реализацией языка) не предназначен для параллелизма, симметричная многопроцессорная обработка не поддерживается.[6] Потоки OCaml в одном процессе выполняются только с разделением времени. Однако существует несколько библиотек для распределенных вычислений, таких как Functory и ocamlnet / Плазма.

Среда разработки

С 2011 года в среду разработки OCaml было добавлено множество новых инструментов и библиотек:

  • Инструменты разработки
    • opam это менеджер пакетов для OCaml, разработанный OCamlPro.
    • Мерлин обеспечивает функциональность, подобную IDE, для нескольких редакторов, включая возврат типа, переход к определению и автозаполнение.
    • Дюна это составная система сборки для OCaml.
    • OCamlformat это средство автоматического форматирования для OCaml.
  • Веб-сайты:
  • Альтернативные компиляторы для OCaml:
    • js_of_ocaml, разработанный Ocsigen team, это оптимизирующий компилятор от OCaml до JavaScript.
    • BuckleScript, который также нацелен JavaScript, с упором на создание удобочитаемого идиоматического вывода JavaScript.
    • ocamlcc - это компилятор от OCaml до C, дополняющий компилятор машинного кода для неподдерживаемых платформ.
    • OCamlJava, разработанный INRIA, представляет собой компилятор от OCaml до Виртуальная машина Java (JVM).
    • OCaPic, разработанный Lip6, представляет собой компилятор OCaml для Микроконтроллеры PIC.

Примеры кода

Фрагменты кода OCaml легче всего изучить, введя их в верхний уровень. Это интерактивный сеанс OCaml, который печатает предполагаемые типы результирующих или определенных выражений. Верхний уровень OCaml запускается простым выполнением программы OCaml:

$ Ocaml     Objective Caml версии 3.09.0#

После этого можно ввести код по запросу «#». Например, чтобы вычислить 1 + 2 * 3:

# 1 + 2 * 3;;-: int = 7

OCaml определяет тип выражения как "int" (a машинная точность целое число ) и дает результат «7».

Привет, мир

Следующая программа "hello.ml":

print_endline "Привет, мир!"

может быть скомпилирован в исполняемый файл байт-кода:

$ ocamlc hello.ml -o привет

или скомпилирован в оптимизированный исполняемый файл с машинным кодом:

$ ocamlopt hello.ml -o привет

и выполнено:

$ ./ПриветПривет, мир!$

Первый аргумент ocamlc, «hello.ml», указывает исходный файл для компиляции, а флаг «-o hello» указывает выходной файл.[7]

Суммирование списка целых чисел

Списки - один из основных типов данных в OCaml. В следующем примере кода определяется рекурсивный функция сумма который принимает один аргумент, целые числа, который должен быть списком целых чисел. Обратите внимание на ключевое слово rec что означает, что функция рекурсивна. Функция рекурсивно выполняет итерацию по заданному списку целых чисел и предоставляет сумму элементов. В матч заявление имеет сходство с C с выключатель элемент, хотя он гораздо более общий.

позволять rec сумма целые числа =                   (* Ключевое слово rec означает «рекурсивный». *)  матч целые числа с  | [] -> 0                              (* Возврат 0, если целые числа пустые                                             список []. *)  | первый :: отдых -> первый + сумма отдых;;  (* Рекурсивный вызов, если целые числа не-                                            пустой список; первый это первый                                             элемент списка, а остальное -                                             список остальных элементов,                                             возможно []. *)
  # сумма [1;2;3;4;5];;  - : int = 15

Другой способ - использовать стандартные функция складывания который работает со списками.

позволять сумма целые числа =  Список.fold_left (весело аккумулятор Икс -> аккумулятор + Икс) 0 целые числа;;
  # сумма [1;2;3;4;5];;  - : int = 15

Поскольку анонимная функция - это просто приложение оператора +, его можно сократить до:

позволять сумма целые числа =  Список.fold_left (+) 0 целые числа

Кроме того, можно опустить аргумент списка, используя частичное применение:

позволять сумма =  Список.fold_left (+) 0

Быстрая сортировка

OCaml позволяет лаконично выражать рекурсивные алгоритмы. В следующем примере кода реализуется алгоритм, похожий на быстрая сортировка который сортирует список в порядке возрастания.

 позволять rec qsort = функция   | [] -> []   | вращаться :: отдых ->     позволять меньше Икс = Икс < вращаться в     позволять оставили, верно = Список.раздел меньше отдых в     qsort оставили @ [вращаться] @ qsort верно

Проблема дня рождения

Следующая программа вычисляет наименьшее количество людей в комнате, для которых вероятность полностью уникальных дней рождения составляет менее 50% ( проблема дня рождения, где для 1 человека вероятность 365/365 (или 100%), для 2 - 364/365, для 3 - 364/365 × 363/365 и т. д.) (ответ = 23).

позволять год_размер = 365.позволять rec birthday_paradox проблема люди =  позволять проблема = (год_размер -. плавать люди) /. год_размер *. проблема  в  если проблема < 0.5 тогда    Printf.printf "answer =% d п" (люди+1)  еще    birthday_paradox проблема (люди+1);;birthday_paradox 1.0 1

Церковные цифры

Следующий код определяет Церковная кодировка из натуральные числа, с преемником (succ) и добавлением (add). Церковная цифра п это функция высшего порядка который принимает функцию ж и ценность Икс и применяет ж к Икс точно п раз. Чтобы преобразовать число Чёрча из функционального значения в строку, мы передаем ему функцию, которая добавляет строку в начало "S" на его вход и постоянную строку "0".

позволять нуль ж Икс = Икспозволять succ п ж Икс = ж (п ж Икс)позволять один = succ нульпозволять два = succ (succ нуль)позволять Добавить n1 n2 ж Икс = n1 ж (n2 ж Икс)позволять нанизывать п = п (весело k -> "S" ^ k) "0"позволять _ = нанизывать (Добавить (succ два) два)

Факториальная функция произвольной точности (библиотеки)

Различные библиотеки доступны напрямую из OCaml. Например, в OCaml есть встроенная библиотека для арифметика произвольной точности. Поскольку факториальная функция растет очень быстро, она быстро выходит за пределы чисел машинной точности (обычно 32- или 64-битных). Таким образом, факториал является подходящим кандидатом для арифметики произвольной точности.

В OCaml модуль Num (теперь замененный модулем ZArith) обеспечивает арифметику произвольной точности и может быть загружен в работающий верхний уровень, используя:

# #использовать "topfind";;# #требовать "число";;# открыто Num;;

Затем факториальную функцию можно записать с использованием числовых операторов произвольной точности. =/, */ и -/ :

# позволять rec факт п =    если п =/ Int 0 тогда Int 1 еще п */ факт(п -/ Int 1);;вал факт : Num.число -> Num.число = <весело>

Эта функция может вычислять факториалы гораздо большего размера, например 120 !:

# string_of_num (факт (Int 120));;- : нить ="6689502913449127057588118054090372586752746333138029810295671352301633557244962989366874165271984981308157637893214090552534408589408121859898481114389650005964960521256960000000000000000000000000000"

Треугольник (графика)

Следующая программа визуализирует вращающийся треугольник в 2D, используя OpenGL:

позволять () =  игнорировать (Перенасыщение.в этом Sys.argv);  Перенасыщение.initDisplayMode ~double_buffer:истинный ();  игнорировать (Перенасыщение.createWindow ~заглавие:"OpenGL Demo");  позволять угол т = 10. *. т *. т в  позволять оказывать () =    GlClear.Чисто [ `цвет ];    GlMat.load_identity ();    GlMat.вращать ~угол: (угол (Sys.время ())) ~z:1. ();    GlDraw.начинается `треугольники;    Список.iter GlDraw.вершина2 [-1., -1.; 0., 1.; 1., -1.];    GlDraw.заканчивается ();    Перенасыщение.swapBuffers () в  GlMat.Режим `просмотр модели;  Перенасыщение.displayFunc ~cb:оказывать;  Перенасыщение.idleFunc ~cb:(Немного Перенасыщение.postRedisplay);  Перенасыщение.mainLoop ()

Привязки LablGL к OpenGL обязательны. Затем программа может быть скомпилирована в байт-код с помощью:

  $ ocamlc -I + lablGL lablglut.cma lablgl.cma simple.ml -o simple

или в собственный код с помощью:

  $ ocamlopt -I + lablGL lablglut.cmxa lablgl.cmxa simple.ml -o простой

или, проще говоря, с помощью команды сборки ocamlfind

  $ ocamlfind opt simple.ml -package lablgl.glut -linkpkg -o simple

и запустите:

  $ ./simple

В OCaml можно разрабатывать гораздо более сложные и высокопроизводительные графические программы в 2D и 3D. Благодаря использованию OpenGL и OCaml полученные программы могут быть кроссплатформенными и компилироваться без каких-либо изменений на многих основных платформах.

Последовательность Фибоначчи

Следующий код вычисляет Последовательность Фибоначчи из числа п введен. Оно использует хвостовая рекурсия и сопоставление с образцом.

позволять выдумать п =  позволять rec fib_aux м а б =    матч м с    | 0 -> а    | _ -> fib_aux (м - 1) б (а + б)  в fib_aux п 0 1

Функции высшего порядка

Функции могут принимать функции как входные и возвращать функции как результат. Например, применяя дважды к функции ж дает функцию, которая применяет ж два раза на свой аргумент.

позволять дважды (ж : 'а -> 'а) = весело (Икс : 'а) -> ж (ж Икс);;позволять inc (Икс : int) : int = Икс + 1;;позволять add2 = дважды inc;;позволять inc_str (Икс : нить) : нить = Икс ^ " " ^ Икс;;позволять add_str = дважды(inc_str);;
  # add2 98;;  - : int = 100  # add_str "Тест";;  - : нить = «Тестовый тест Тестовый тест»

Функция дважды использует переменную типа чтобы указать, что его можно применить к любой функции ж отображение из типа себе, а не только int-> int функции. Особенно, дважды может применяться даже к самому себе.

  # позволять четыре раза ж = (дважды дважды) ж;;  вал четыре раза : ('а -> 'а) -> 'а -> 'а = <весело>  # позволять add4 = четыре раза inc;;  вал add4 : int -> int = <весело>  # add4 98;;  - : int = 102

Производные языки

MetaOCaml

MetaOCaml[8] это многоступенчатое программирование расширение OCaml, позволяющее инкрементную компиляцию новых Машинный код во время выполнения. При некоторых обстоятельствах возможно значительное ускорение при использовании многоступенчатого программирования, потому что более подробная информация о данных для обработки доступна во время выполнения, чем в обычное время компиляции, поэтому инкрементный компилятор может оптимизировать многие случаи проверки условий и т. Д.

В качестве примера: если во время компиляции известно, что некоторые степенная функция Икс -> Икс^п требуется часто, но значение п известно только во время выполнения, в MetaOCaml можно использовать двухступенчатую функцию мощности:

 позволять rec мощность п Икс =   если п = 0   тогда .<1>.   еще     если четное п     тогда sqr (мощность (п/2) Икс)     еще .<.~Икс *. .~(мощность (п - 1) Икс)>.

Как только п известно во время выполнения, может быть создана специализированная и очень быстрая функция мощности:

 .<весело Икс -> .~(мощность 5 .<Икс>.)>.

Результат:

 весело x_1 -> (x_1 *     позволять y_3 =          позволять y_2 = (x_1 * 1)         в (y_2 * y_2)     в (y_3 * y_3))

Новая функция компилируется автоматически.

Другие производные языки

  • AtomCaml предоставляет примитив синхронизации для атомарного (транзакционного) выполнения кода.
  • Эмили (2006) - это подмножество OCaml 3.08, которое использует верификатор правил проектирования для обеспечения объектно-способная модель безопасность принципы.
  • F # это .NET Framework язык на основе OCaml.
  • Fresh OCaml упрощает управление именами и привязками.
  • GCaml добавляет к OCaml экстенсиональный полиморфизм, что позволяет осуществлять перегрузку и маршаллинг с учетом типов.
  • JoCaml объединяет конструкции для разработки параллельных и распределенных программ.
  • OCamlDuce расширяет OCaml такими функциями, как выражения XML и типы регулярных выражений.
  • OCamlP3l - это параллельное программирование система на основе OCaml и языка P3L.
  • Хотя это не совсем отдельный язык, Причина является альтернативой OCaml синтаксис и набор инструментов для OCaml, созданного в Facebook.

Программное обеспечение, написанное на OCaml

Пользователи

Несколько десятков компаний в той или иной степени используют OCaml.[14] Известные примеры включают:

Рекомендации

  1. ^ «Модули». Получено 22 февраля 2020.
  2. ^ «Релизы - OCaml». ocaml.org.
  3. ^ "История OCaml". Получено 24 декабря 2016.
  4. ^ Еженедельные новости Linux.
  5. ^ "ocaml / asmcomp в магистрали · ocaml / ocaml · GitHub". GitHub. Получено 2 мая 2015.
  6. ^ "Архивы списка рассылки Caml> Сообщение от Ксавье Леруа". Получено 2 мая 2015.
  7. ^ https://caml.inria.fr/pub/docs/manual-ocaml/comp.html
  8. ^ oleg-at-okmij.org. «BER MetaOCaml». okmij.org.
  9. ^ "Messenger.com теперь на 50% преобразован в разум · Причину". причинаml.github.io. Получено 2018-02-27.
  10. ^ "Flow: средство проверки статического типа для JavaScript". Поток.
  11. ^ «Сделать вывод статического анализатора». Сделать вывод.
  12. ^ «GitHub - facebook / pyre-check: эффективная проверка типов для python». 9 февраля 2019 г. - через GitHub.
  13. ^ «Спецификация WebAssembly, эталонный интерпретатор и набор тестов: WebAssembly / spec». 10 февраля 2019 г. - через GitHub.
  14. ^ «Компании, использующие OCaml». OCaml.org. Получено 17 августа 2014.
  15. ^ «BuckleScript: Выпущена версия 1.0! | Технологии Bloomberg». Технологии в Bloomberg. 8 сентября 2016 г.. Получено 21 мая 2017.
  16. ^ Ярон Минский (1 ноября 2011 г.). "OCaml для масс". Получено 2 мая 2015.
  17. ^ https://ocaml.org/learn/companies.html

внешняя ссылка