Я понимаю, почему вы хотите это сделать, но, к сожалению, это может быть только иллюзией, что классы Haskell кажутся «открытыми» в том виде, в котором вы говорите. Многие люди считают, что такая возможность является ошибкой в спецификации Haskell, по причинам, которые я объясню ниже. В любом случае, если это действительно не подходит для экземпляра, который вам нужно объявить либо в модуле, где объявлен класс, либо в модуле, где объявлен тип, это, вероятно, знак того, что вы должны использовать newtype
или какую-либо другую оболочку вокруг вашего типа.
Причины, по которым следует избегать бесхозных экземпляров, лежат гораздо глубже, чем удобство компилятора. Эта тема довольно противоречивая, как вы можете видеть из других ответов. Чтобы сбалансировать дискуссию, я собираюсь объяснить точку зрения, согласно которой никогда и никогда не следует писать бесхозные экземпляры, что, на мой взгляд, является мнением большинства опытных хаскеллеров. Мое собственное мнение находится где-то посередине, и я объясню это в конце.
Проблема проистекает из того факта, что когда существует более одного объявления экземпляра для одного и того же класса и типа, в стандартном Haskell нет механизма, чтобы указать, какой из них использовать. Скорее программа отклоняется компилятором.
Самый простой эффект от этого заключается в том, что у вас может быть отлично работающая программа, которая внезапно перестанет компилироваться из-за изменения, которое кто-то внесет в некоторую удаленную зависимость вашего модуля.
Еще хуже то, что работающая программа может начать сбой во время выполнения из-за отдаленного изменения. Вы можете использовать метод, который, как вы предполагаете, исходит из объявления определенного экземпляра, и его можно молча заменить другим экземпляром, который достаточно отличается, чтобы заставить вашу программу начать необъяснимый сбой.
Люди, которым нужны гарантии того, что эти проблемы никогда не возникнут с ними, должны следовать правилу, согласно которому, если кто-либо где-либо когда-либо объявил экземпляр определенного класса для определенного типа, никакой другой экземпляр никогда не должен быть объявлен снова в любой написанной программе. кем угодно. Конечно, есть обходной путь использования a newtype
для объявления нового экземпляра, но это всегда как минимум незначительное неудобство, а иногда и серьезное. Так что в этом смысле те, кто намеренно пишет экземпляры-сироты, довольно невежливы.
Так что же делать с этой проблемой? Лагерь по борьбе с сиротскими экземплярами говорит, что предупреждение GHC - это ошибка, это должна быть ошибка, которая отклоняет любую попытку объявить сиротский экземпляр. А пока мы должны проявлять самодисциплину и избегать их любой ценой.
Как вы видели, есть те, кого эти потенциальные проблемы не слишком беспокоят. Они на самом деле поощряют использование сиротских экземпляров в качестве инструмента для разделения проблем, как вы предлагаете, и говорят, что нужно просто в каждом конкретном случае убедиться, что проблем нет. Я достаточно раз испытывал неудобства из-за чужих сиротских случаев, чтобы убедиться, что такое отношение слишком бесцеремонно.
Я думаю, что правильным решением было бы добавить расширение к механизму импорта Haskell, которое бы контролировало импорт экземпляров. Это не решит проблемы полностью, но окажет некоторую помощь в защите наших программ от ущерба со стороны сиротских экземпляров, которые уже существуют в мире. И затем, со временем, я мог бы убедиться, что в некоторых ограниченных случаях, возможно, сиротский экземпляр может быть не так уж и плох. (И именно это искушение является причиной того, что некоторые в лагере противников сиротства выступают против моего предложения.)
Из всего этого я пришел к выводу, что, по крайней мере, на данный момент, я настоятельно рекомендую вам избегать объявления каких-либо сиротских экземпляров, чтобы быть внимательным к другим, хотя бы по другой причине. Используйте файл newtype
.