2013-05-27 14 views
8

Czytając książkę Real world Haskell geting poniżej przykład z nakładających przypadkachNakładające się przypadki, w Haskell

instance (JSON a) => JSON [a] where 
    toJValue = undefined 
    fromJValue = undefined 

instance (JSON a) => JSON [(String, a)] where 
    toJValue = undefined 
    fromJValue = undefined 

ghci> toJValue [("foo","bar")] 

<interactive>:1:0: 
    Overlapping instances for JSON [([Char], [Char])] 
     arising from a use of `toJValue' at <interactive>:1:0-23 
Matching instances: 
    instance (JSON a) => JSON [a] 
    -- Defined at BrokenClass.hs:(44,0)-(46,25) 
    instance (JSON a) => JSON [(String, a)] 
    -- Defined at BrokenClass.hs:(50,0)-(52,25) 
    In the expression: toJValue [("foo", "bar")] 
    In the definition of `it': it = toJValue [("foo", "bar")] 

Według mojego rozumienia tego nie będzie nakładających się, jak [a] nie powinien być wybór, ponieważ ograniczenie JSON [a] był taki, że "a" musi być samą instancją JSON. Nie ma instancji JSON dla (String, a).

Odpowiedz

17

Według mojego rozumienia tego nie będzie nakładających się, jak [a] nie powinien być wybór, ponieważ Ograniczenie JSON [a], że a musi być instancją sam z JSON. Nie ma instancji JSON dla (String, a).

To nieporozumienie. GHC dokonuje selekcji instancji, biorąc pod uwagę tylko nagłówek instancji, a nie wszelkie ograniczenia instancji.

instance (JSON a) => JSON [a] where 

oznacza dla celów selekcji, przykładowo takie same jak

instance JSON [a] where 

również kontekst

instance (JSON a) => JSON [(String, a)] where 

jest ignorowany przykład wybranie.

Zatem GHC widzi dwie instancje

instance JSON [a] 
instance JSON [(String, a)] 

i oboje odpowiada wymaganemu

instance JSON [(String, String)] 

Oznacza to, że mają nakładania (niezależnie od tego, jakie przypadki faktycznie istnieją i jakie są ograniczenia każdej z dwóch przypadkach ma).

Jeśli wybrano instancję, to ograniczenia są brane pod uwagę, a jeśli nie są spełnione, jest to błąd typu.

+0

dzięki za bardzo szczegółowe wyjaśnienie –

+0

Przy okazji: nieco później w książce zaznacza się, że można użyć "pragnienia OverlappingInstances", aby "rozwiązać" "problem" opisany w tej odpowiedzi. Osobiście nie rozumiem, dlaczego tak jest. Mam nadzieję, że zignoruje to pewnego dnia. – Brendan

5

one istnieć

ghci> :i ToJSON 
... 
instance ToJSON [Char] 
... 
instance (ToJSON a, ToJSON b) => ToJSON (a, b) 

Więc nie byłoby nakładanie nawet jeśli GHC wziął pod uwagę kontekst (patrz odpowiedź Daniela Fischera).

Powiązane problemy