2014-04-02 17 views
12

Znalazłem ten kod w pakiecie Unm-Hip. Więc Pixel to funkcja?Co oznacza gwiazda w tym kodzie haskell?

class Imageable i where 
    type Pixel i :: * 
    rows :: i -> Int 
    cols :: i -> Int 
    ref :: i -> Int -> Int -> (Pixel i) 
    makeImage :: Int -> Int -> PixelOp (Pixel i) -> i 
    pixelList :: i -> [Pixel i] 
    pixelList i = [ ref i r c | r <- [0..(rows i - 1)], c <- [0..(cols i - 1)]] 

Odpowiedz

15

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.

+0

Czy wiesz, dlaczego autor kodu korzysta z tego projektu? – osager

+2

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. –

1

"Czy Pixel jest funkcją?"

Pixel to funkcja poziomu. Zajmuje jeden typ (który musi być egzemplarzem Imageable) i zwraca rodzaj "*". Na podstawie jego użycia w przykładowym kodzie, typ wejścia musi być również rodzaju "*". Pixel jest więc bardzo podobny do Maybe, oba są "typowymi konstruktorami" rodzaju "* -> *", zapewniasz im "prosty typ" i zwracają "prosty typ". Są one również ważne w tych samych lokalizacjach. Podobnie jak nie możesz mieć funkcji typu "Foo -> Może", nie będziesz mógł również mieć funkcji typu "Bar -> Piksel".

+0

A zatem słowo kluczowe "type" nie ma takiego samego odpowiednika jak słowo kluczowe "haskell"? Jeśli jest tak, jak powiedziałeś, dlaczego nie jest napisane w ten sposób: 'wpisz Pixel :: i -> *' – osager

+1

@osager Jest powiązany, ale nie taki sam. Po podaniu instancji (Imagable my_image) definicja Pixela musi być istniejącym typem, a (Pixel my_image) będzie aliasem/synonimem tego typu. Jest to rozszerzenie GHC zwane rodzinami (open). –