Введение

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

Введение

Типирование уникальности лучше всего объяснить на примере. Рассмотрим функцию `readLine`, которая читает следующую строку текста из заданного файла:

function `readLine`(File f) returns String
return line where
String line = doImperativeReadLineSystemCall(f)
end
end

Теперь `doImperativeReadLineSystemCall` читает следующую строку из файла, используя системный вызов уровня ОС, который имеет побочный эффект – изменение текущей позиции в файле. Но это нарушает референтную прозрачность, поскольку многократный вызов этой функции с одним и тем же аргументом будет возвращать разные результаты, так как текущая позиция в файле будет изменяться. Это, в свою очередь, приводит к нарушению референтной прозрачности для `readLine`, поскольку она вызывает `doImperativeReadLineSystemCall`. Однако, используя типирование уникальности, мы можем создать новую версию `readLine`, которая будет референтно прозрачной, даже если она построена на основе функции, которая не является референтно прозрачной:

function `readLine2`(unique File f) returns (unique File, String)
return (differentF, line) where
String line = doImperativeReadLineSystemCall(f)
File differentF = newFileFromExistingFile(f)
end
end

Ключевое слово `unique` указывает, что тип `f` является уникальным; то есть, вызывающий код `readLine2` не сможет обратиться к `f` повторно после возврата `readLine2`, и это ограничение обеспечивается системой типов. И поскольку `readLine2` не возвращает `f` напрямую, а возвращает новый, отличный файловый объект `differentF`, это означает, что `readLine2` невозможно будет вызвать с аргументом `f` снова, тем самым сохраняя референтную прозрачность и позволяя побочным эффектам происходить.

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

Типы уникальности реализованы в функциональных языках программирования, таких как Clean, Mercury, SAC и Idris. Иногда они используются для выполнения операций ввода-вывода в функциональных языках вместо монад. Для языка программирования Scala разработано расширение компилятора, использующее аннотации для обработки уникальности в контексте обмена сообщениями между акторами.

Отношение к линейной типизации

Уникальный тип очень похож на линейный тип, настолько, что эти термины часто используются как синонимы, но между ними есть существенная разница: фактическая линейная типизация позволяет приводить нелинейное значение к линейному типу, при этом сохраняя несколько ссылок на него. Уникальность гарантирует отсутствие других ссылок на значение, а линейность – невозможность создания новых ссылок на него. Различие между линейностью и уникальностью особенно заметно в контексте нелинейности и не уникальности, однако их можно объединить в единую систему типов.