Я розумію, чому ви хочете це зробити, але, на жаль, це може бути лише ілюзією того, що класи Haskell здаються "відкритими" так, як ви говорите. Багато людей вважають, що можливість зробити це є помилкою в специфікації Haskell, з причин, які я поясню нижче. У будь-якому випадку, якщо це дійсно не підходить для екземпляра, вам потрібно оголосити або в модулі, де оголошено клас, або в модулі, де оголошено тип, це, мабуть, знак того, що ви повинні використовувати newtype
оболонку або якусь іншу навколо вашого типу.
Причини, через які слід уникати випадків-сиріт, набагато глибші, ніж зручність компілятора. Ця тема досить суперечлива, як ви можете бачити з інших відповідей. Щоб збалансувати дискусію, я збираюся пояснити точку зору, що ніколи, ніколи не слід писати інциденти-сироти, що, на мою думку, є думкою більшості серед досвідчених хаскелерів. Моя власна думка знаходиться десь посередині, що я поясню в кінці.
Проблема випливає з того, що коли для одного класу та типу існує більше одного оголошення екземпляра, у стандартному Haskell не існує механізму, який би вказав, який використовувати. Швидше, програма відхиляється компілятором.
Найпростіший ефект цього полягає в тому, що ви можете мати ідеально працюючу програму, яка раптово припинить компіляцію через зміни, які хтось інший робить у якійсь далекій залежності вашого модуля.
Ще гірше, можливо, що робоча програма може почати збій під час виконання через віддалену зміну. Ви можете використовувати метод, який, як ви припускаєте, походить з певного оголошення екземпляра, і його можна мовчки замінити іншим екземпляром, який є просто достатньо іншим, щоб ваша програма могла незрозуміло почати збій.
Люди, які хочуть гарантувати, що з ними ніколи не трапиться цих проблем, повинні дотримуватися правила, згідно з яким якщо хтось і де-небудь коли-небудь оголосив екземпляр певного класу для певного типу, жоден інший екземпляр не повинен бути оголошений знову в будь-якій написаній програмі будь-ким. Звичайно, є обхідний шлях використання a newtype
для оголошення нового екземпляру, але це завжди є принаймні незначною незручністю, а іноді і основною. Отже, у цьому сенсі ті, хто навмисно пишуть екземпляри-сироти, є досить неввічливими.
То що слід зробити з цією проблемою? У таборі, що описується анти-сиротою, кажуть, що попередження GHC - це помилка, це має бути помилка, яка відхиляє будь-яку спробу оголосити сироту-екземпляр. Тим часом ми повинні проявляти самодисципліну і уникати їх будь-якою ціною.
Як ви вже переконалися, є люди, яких не так хвилюють ці потенційні проблеми. Вони насправді заохочують використовувати випадки-сироти як інструмент для розділення проблем, як ви пропонуєте, і кажуть, що потрібно просто переконатись у кожному конкретному випадку, щоб не було проблем. Мені достатньо разів приносили незручності інстанції інших людей, щоб переконатись, що таке ставлення занадто кавалерне.
Я думаю, правильним рішенням було б додати розширення до механізму імпорту Haskell, яке контролювало б імпорт екземплярів. Це не дозволить вирішити проблеми повністю, але це допоможе захистити наші програми від збитків від випадків-сиріт, які вже існують у світі. І тоді, з часом, я можу переконатися, що в певних обмежених випадках, можливо, приклад сироти може бути не таким поганим. (І саме ця спокуса є причиною того, що дехто в таборі інцидентів проти сиріт виступає проти моєї пропозиції).
З усього цього я роблю висновок, що, принаймні на даний момент, я настійно рекомендую уникати заявляти про будь-які випадки-сироти, щоб бути уважними до інших, якщо не з інших причин. Використовуйте a newtype
.