Повторно использовать и расширять определенный тип в Ocaml - PullRequest
11 голосов
/ 30 июля 2011

Есть ли в Ocaml простая конструкция / стиль для расширения определенного типа?

Скажем, если у нас есть логический тип

bool2 = True | False 

Теперь мы хотим расширить его для 3-значной логики.В Ocaml есть что-то более элегантное, чем переопределение bool2, например:

bool3 = True | False | ThirdOne

Ответы [ 3 ]

14 голосов
/ 30 июля 2011

Полиморфные варианты предоставляют эту функциональность:

type bool2 = [ `True | `False ]
type bool3 = [ bool2 | `Third_one ]

Вот и все.

Существует еще один полезный ярлык для полиморфных вариантов.При сопоставлении с образцом используйте имя типа, которому предшествует #:

let is_bool2 = function
    #bool2 -> true
  | `Third_one -> false

Полиморфные варианты следует использовать с осторожностью, поскольку они могут легко привести к путанице в сообщениях об ошибках.Если исходный тип bool2 не является полиморфным вариантом в любом случае, объединение двух типов достигается следующим образом.Давайте предположим, что bool2 является базовым типом bool, наше определение с использованием классических вариантов:

type bool3 = Bool of bool | Third_one

При сопоставлении с образцом компилятор проверяет, что все случаи покрыты, не требуя аннотаций типов.Это выглядит так:

match x with
| Bool true -> ...
| Bool false -> ...
| Third_one -> ...
8 голосов
/ 31 июля 2011

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

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

Этот способ, конечно, имеет некоторые недостатки. Одним из них является то, что изменение определения типа, а затем изменение каждого варианта использования может не сработать с вашей обычной практикой тестирования компиляции: если вы сделаете это на большой базе кода, у вас будет много важных вещей, которые нужно сделать до компиляции проекта снова чисто (и, следовательно, может быть проверено). Вы можете разделить вашу модификацию на несколько патчей в вашей системе контроля версий, но это означает, что некоторые промежуточные зафиксированные состояния не компилируются, что не очень приятно. Другая возможность состоит в том, чтобы изменить это место только для добавления сбоя во время выполнения (| Third_one -> assert false), тогда у вас будет скомпилированный код, и вы можете исправить эти сбои, как они происходят во время выполнения во время тестирования приложения. Но я все еще думаю, что обратная связь со статическим компилятором - хорошая помощь для поддержки кода.

Существует также опция оборачивания алгебраического типа данных в «расширенный алгебраический тип данных» type bool3 = New | Old of bool2, который обсуждается в ссылке, которую вы даете в качестве комментария ответа Мартина. Это может быть хорошим способом перехода от одного типа данных к другому, не прерывая компиляцию, но в долгосрочной перспективе это будет болезненно, особенно если вы кладете больше этих расширений друг на друга.

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

PS: в отношении полиморфных вариантов и их связи с проблемой выражения обязательной статьей является Повторное использование кода через полиморфные варианты Жака Гаррига.

2 голосов
/ 11 марта 2017

В зависимости от поставленной задачи, вы также можете найти Расширенные типы вариантов полезными.Больше информации и вариантов использования здесь .

type bool = ..
type bool +=
    | True
    | False

(* Elsewhere *)
type bool +=
    | Third_one
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...