Jako rozszerzenie standardowego Haskella można sobie poradzić z "rodzajami". Rodzaje są rodzajem bardzo podstawowego systemu typów dla typów i konstruktorów typów. Rodzaj *
to prosty typ, taki jak Int
. Rodzaj * -> *
jest konstruktorem typu, który przyjmuje typ i generuje typ, taki jak Maybe
: przekazuje go jako typ, taki jak Int
, jako argument, a otrzymasz typ Maybe Int
.
Drugim rozszerzeniem użytym w tym kodzie (którego początkowo nie zauważyłem, ponieważ utracono wcięcie) są skojarzone typy. Typowa czcionka w standardowym Haskell może określać wiele funkcji, które musi obsługiwać typ. Z powiązanymi typami może dodatkowo określać typy i konstruktory typów powiązane z typem.
tutaj, oznacza to, że typ i
to wystąpienie Imageable
(to zachowuje się jak obraz) musi mieć powiązany pikseli typu Pixel i
i musi być typu prostego (rodzaj *
) nie konstruktora typu.
Czy wiesz, dlaczego autor kodu korzysta z tego projektu? – osager
Nie ma wielkiego wyboru. Masz typ, który reprezentuje obraz, a typek potrzebuje funkcji, które zajmują się pojedynczym pikselem na obrazie. Potrzebujesz sposobu, aby dowiedzieć się, jaki jest typ tego piksela. Możesz to naprawić, ale to nie jest zbyt elastyczne. Możesz uczynić z Imageable wieloparametrową czcionkę typograficzną na obrazie i jego pikselu, ale wtedy potrzebujesz funkcjonalnych zależności lub niejednoznaczności typu, które doprowadzą cię do szaleństwa, i nadal musisz wspomnieć o typie piksela w każdym sygnaturze, która używa klasy. Powiązane typy są znacznie czystsze i łatwiejsze. –