2012-01-31 20 views
7

W pewnym sensie jest to krok wstecz w stosunku do mojego wcześniejszego pytania, ale ... Czy ktoś może mi przypomnieć, dlaczego ten nie działa?Typy elementów kontenera

 
class Container c e where 
    empty :: c 
    insert :: e -> c -> c 

instance Container [x] x where 
    empty = [] 
    insert = (:) 

instance Container ByteString Word8 where 
    empty = BIN.empty 
    insert = BIN.cons 

instance Ord x => Container (Set x) x where 
    empty = SET.empty 
    insert = SET.insert 

Oczywiście, gdyby to było tak proste, nikt nie chciałby wymyślić zależności funkcjonalnych ani powiązanych typów. Więc jaki jest problem z powyższym?

+0

Spróbuj go użyć. Wkrótce dostaniesz skargi na niejednoznaczne przeciążanie. – augustss

Odpowiedz

10

Nie ma nic, co mogłoby Cię powstrzymać przed dodaniem instance Container [Int] Int i instance Container [Int] Char, a gdy pytasz o empty :: [Int], kompilator nie ma możliwości poznania, z której instancji ma pochodzić.

"Ah, ale mam tylko instance Container [Int] Int," mówisz. "I tak instance Container [Int] Char i tak byłby błędem."

Ale kompilator nie może wiedzieć, że w przyszłości nie doda się instance Container [Int] Char, a jeśli to zrobisz, nie będzie mógł złamać istniejącego kodu.

Dlatego musimy jakiś sposób informując kompilator, że

  • pierwszy parametr Container jednoznacznie określa drugi parametr Container
  • jeśli widzi różne przypadki, które różnią się tylko w drugim typie, który wskazuje, błąd

Wprowadź zależności funkcjonalne.

+0

Wiedziałem, że muszę zapomnieć o czymś oczywistym ... – MathematicalOrchid

Powiązane problemy