Ogólne pytanie brzmi, która struktura modułów jest wygodniejsza przy dodawaniu wystąpień dla istniejących obiektów? Jakie są plusy i minusy?Jak organizować moduły Haskella z instancjami: przyklejać do typu danych w porównaniu do typu?
Załóżmy, że chcę dodać instancję NFData dla typu Seq. Mogę umieścić go w:
Data.Sequence.Extra
(tak samo odbywa się w pakiecie vty)Data.Sequence.Instances.NFData
(bardziej precyzyjna)Control.DeepSeq.Instances
Control.DeepSeq.Instances.Sequence
To sprawa gdy nie jestem właścicielem ani klasy typów, ani typu danych. Inną często spotykaną sytuacją jest posiadanie klasy typu i chęć dodawania instancji dla typów danych z jakiegoś "ciężkiego" pakietu z Hackage, takiego jak OpenGL. Powiedzmy, że klasa typu I zaprojektowana jest bardzo lekka i nie ma bezpośredniego związku z OpenGL. Nie chcę, aby moja klasa była zależna od "ciężkiego" pakietu, więc chcę umieścić instancje OpenGL w osobnym module (to moje intuicyjne uczucie, jeśli masz inne zdanie, porozmawiajmy o tym). Więc, co to moduł powinien być:
MyClass.Instances.OpenGL
Graphics.Rendering.OpenGL.Extra
(wraz z instancjami dla innych klas)Graphics.Rendering.OpenGL.Instances.MyClass
Co jest bardziej elastyczne rozwiązanie? W pewnym momencie OpenGL można zastąpić inną biblioteką lub można również wymienić MyClass. Czy są jakieś subtelne niuanse?
Ponadto, który system jest lepszy, czy wybrać MyClass.Instances
Wariant:
MyClass.Class
moduł do samej klasy i podstawowych przypadkach iMyClass
modułu ponownego eksportu to (a możeMyClass.Instances
)MyClass
modułu dla klasy i podstawowy instancje iMyClass.All
reexportuje wszystko modułMyClass
dla klasy i podstawowych instancji oraz brak modułu do ponownego eksportu.
To co robisz nazywa się "instancjami sierocymi" i jest uważane za złe, ponieważ ułatwia definiowanie wielu wystąpień tej samej klasy dla tego samego typu i sprawia, że dobre biblioteki są niekompatybilne ze sobą. Było jeszcze inne pytanie omawiające je szczegółowo: http://stackoverflow.com/questions/3079537/orphaned-instances-in-haskell. – Rotsor
Dla problemu Rotsora - biblioteka "ogólna" nie powinna zajmować się wdrażaniem instancji dla klas/typów danych, których nie definiuje. Dla biblioteki prywatnej lub pliku wykonywalnego/aplikacji jest to w porządku, ale biblioteka publiczna nie powinna tego robić. W przypadku pierwotnego problemu - problem nie polega na tym, gdzie w przestrzeni nazw zdefiniowano instancję, ale że może istnieć więcej niż jedna biblioteka udostępniająca instancję. Najlepszym rozwiązaniem jest prawdopodobnie posiadanie pakietów "instancji" w Hackage, gdzie programiści dostarczają instancje kanoniczne dla klas/typów danych poza Bazą. –
@Rotsor, to dobra uwaga (chociaż nie ma wspólnej opinii na temat komentarza pod linkiem). Czy wynika z tego, że kiedy posiadam klasę typu, zwiążę z nią instancje? – modular