Rozumiem, dlaczego chcesz to zrobić, ale niestety może to być tylko złudzenie, że zajęcia Haskell wydają się być „otwarte” w sposób, w jaki to mówisz. Wiele osób uważa, że możliwość zrobienia tego jest błędem w specyfikacji Haskell, z powodów, które wyjaśnię poniżej. W każdym razie, jeśli naprawdę nie jest to odpowiednie dla instancji, musisz być zadeklarowany albo w module, w którym zadeklarowano klasę, albo w module, w którym jest zadeklarowany typ, prawdopodobnie jest to znak, że powinieneś użyć newtype
lub innego opakowania wokół Twojego typu.
Powody, dla których należy unikać osieroconych instancji, są znacznie głębsze niż wygoda kompilatora. Ten temat jest dość kontrowersyjny, jak widać na podstawie innych odpowiedzi. Aby zrównoważyć dyskusję, wyjaśnię punkt widzenia, że nigdy, przenigdy nie powinno się pisać instancji osieroconych, co, jak sądzę, jest zdaniem większości wśród doświadczonych haskellerów. Moja własna opinia jest gdzieś pośrodku, co wyjaśnię na końcu.
Problem wynika z faktu, że gdy istnieje więcej niż jedna deklaracja instancji dla tej samej klasy i typu, w standardowym Haskellu nie ma mechanizmu określającego, którego użyć. Program jest raczej odrzucany przez kompilator.
Najprostszym skutkiem tego jest to, że możesz mieć doskonale działający program, który nagle przestałby kompilować z powodu zmiany dokonanej przez kogoś innego w jakiejś odległej zależności od twojego modułu.
Co gorsza, działający program może zacząć się zawieszać w czasie wykonywania z powodu odległej zmiany. Możesz użyć metody, która, jak zakładasz, pochodzi z określonej deklaracji instancji i może zostać po cichu zastąpiona inną instancją, która jest po prostu inna na tyle, aby spowodować, że program zacznie się zawieszać w niewytłumaczalny sposób.
Osoby, które chcą mieć gwarancję, że te problemy nigdy się im nie przytrafią, muszą przestrzegać zasady, że jeśli ktokolwiek, gdziekolwiek, kiedykolwiek zadeklarował wystąpienie określonej klasy dla określonego typu, żadne inne wystąpienie nie może być ponownie zadeklarowane w żadnym napisanym programie przez kogokolwiek. Oczywiście istnieje obejście polegające na użyciu a newtype
do zadeklarowania nowej instancji, ale jest to zawsze przynajmniej niewielka niedogodność, a czasem poważna. W tym sensie ci, którzy celowo piszą przypadki osierocone, są raczej niegrzeczni.
Więc co należy zrobić z tym problemem? Obóz anty-osieroconych-instancji twierdzi, że ostrzeżenie GHC jest błędem, musi to być błąd, który odrzuca każdą próbę zadeklarowania osieroconej instancji. W międzyczasie musimy ćwiczyć samodyscyplinę i unikać ich za wszelką cenę.
Jak widzieliście, są tacy, którzy nie przejmują się takimi potencjalnymi problemami. Jak sugerujesz, zachęcają do korzystania z instancji osieroconych jako narzędzia do oddzielania obaw i mówią, że należy po prostu upewnić się, że nie ma problemu w każdym przypadku z osobna. Wystarczająco wiele razy przeszkadzały mi przypadki sierot innych ludzi, aby przekonać się, że taka postawa jest zbyt nonszalancka.
Myślę, że właściwym rozwiązaniem byłoby dodanie rozszerzenia do mechanizmu importu Haskella, które kontrolowałoby import instancji. Nie rozwiązałoby to całkowicie problemów, ale pomogłoby w ochronie naszych programów przed uszkodzeniami powodowanymi przez instancje sieroce, które już istnieją na świecie. A potem, z czasem, mógłbym się przekonać, że w pewnych ograniczonych przypadkach przypadek sieroty może nie być taki zły. (I właśnie ta pokusa jest powodem, dla którego niektórzy w obozie przeciw instancji sierocym są przeciwni mojej propozycji).
Mój wniosek z tego wszystkiego jest taki, że przynajmniej na razie stanowczo radziłbym, abyście unikali ogłaszania jakichkolwiek przypadków osieroconych, aby byli uważni na innych, jeśli nie ma innego powodu. Użyj newtype
.