2015-05-17 27 views
6

Kody wygląda następująco:W Haskell, jak automatycznie wyprowadzić taką niestandardową klasę?

class MyAnd a where 
    myAnd :: (Show a) => a -> a -> String 
    x `myAnd` y = (show x) ++ " and " ++ (show y) 

data TrafficLight = Red | Yellow | Green deriving(Show, MyAnd) 

MyAnd Tutaj jest klasa typ, który posiada funkcję myAnd, myślałem, że jest nazwą rodzajową i jedynym ograniczeniem jest a musi posiada instancję Show klasy ..

W typie TrafficLight pochodzi już z klasy typu Show. Jednak gdy skompilowałem kody, kompilator narzeka

Can't make a derived instance of ‘MyAnd TrafficLight’: 
     ‘MyAnd’ is not a derivable class 
    In the data declaration for ‘TrafficLight’ 
Failed, modules loaded: none. 

Czy ktoś ma pomysły na ten temat?

Odpowiedz

8

Nie można używać wyprowadzania z klasami zdefiniowanymi przez użytkownika. Zwykle deriving automatycznie generuje kod dla metod danej klasy, co jest możliwe tylko dlatego, że kompilator wie, jakie metody powinny wykonać, i może w ten sposób wygenerować odpowiednie implementacje w oparciu o strukturę twojego typu. Jest to oczywiście niemożliwe w przypadku klas zdefiniowanych przez użytkownika, ponieważ kompilator nie ma możliwości dowiedzenia się, jak powinny zachowywać się te metody.

W twoim przypadku wygląda na to, że chcesz tylko użyć domyślnych implementacji jednej metody, którą twoja klasa ma, więc żadna implementacja nie musiałaby zostać wygenerowana przez kompilator. Oczywiście oznacza to, że deriving nie jest w ogóle konieczne i można po prostu użyć deklaracji instancji bez ciała.

PS: Jeśli zawsze będziesz chciał użyć domyślnej implementacji metody, może to w jakikolwiek sensie nie używać klasy, ale po prostu zdefiniuj myAnd jako funkcję.

+0

To prawda, kompilator nie wie, jakie metody powinny wykonać. Ale może warto dodać do tego język, żeby to powiedzieć. Powiązane: http://stackoverflow.com/a/3864801/524504 – masterxilo

7

Dla tego konkretnego problemu, można po prostu uniknąć definiowania niestandardowej klasy:

data TrafficLight = Red | Yellow | Green deriving Show 

myAnd :: (Show a) => a -> a -> String 
x `myAnd` y = (show x) ++ " and " ++ (show y) 

Teraz myAnd dotyczy TrafficLight s (podobnie jak wszystkie inne Show zdolnymi typy).

Powiązane problemy