2013-04-04 32 views
8

Załóżmy, że mam następujące klasy:klasy dziedziczenie typu Haskell

class P a where 
    nameOf :: a -> String 

chciałbym oświadczyć, że wszystkie instancje tej klasy są automatycznie przypadki Show. Moja pierwsza próba będzie następujący:

instance P a => Show a where 
    show = nameOf 

moja pierwsza próba, aby przejść tędy wczoraj spowodowało warren królika rozszerzeń językowych: I po raz pierwszy powiedział, aby przełączyć się na elastycznych przypadkach następnie nierozstrzygalne instancje, a następnie pokrywające się przypadki, i wreszcie otrzymujemy błąd dotyczący nakładania się deklaracji instancji. Poddałem się i wróciłem do powtórzenia kodu. Zasadniczo jednak wydaje się to bardzo prostym żądaniem, które powinno być łatwo zaspokojone.

Więc dwa pytania:

  1. Czy jest trywialnie prosta droga do tego, że ja po prostu brakowało zrobić?
  2. Dlaczego pojawia się problem nakładających się instancji? Rozumiem, dlaczego potrzebuję UndecidableInstances, ponieważ wydaje mi się, że naruszam warunek Patersona, ale tutaj nie ma nakładających się instancji: nie ma nawet takich przypadków, nawet P. Dlaczego typechecker wierzy, że istnieje wiele instancji dla Show Double (jak się wydaje w przypadku tego zabawkowego przykładu)?
+3

Nakładanie (i rozdzielczość przeciążania) jest określane przez samą instancję "Show a", więc faktycznie nakłada się z każdą inną instancją 'Show'. – augustss

+1

Załóżmy, że deklarujesz wystąpienie 'P Int' i masz już instancję' Show Int', co spowoduje nakładanie się instancji dla Show. – Satvik

+0

@Satvik Pewnie, z tym wyjątkiem, że nie mam w pobliżu instancji 'P Int'. Spodziewam się błędu, jeśli spróbuję stworzyć "P Int", ale nie po prostu oświadczając, że może istnieć. – Impredicative

Odpowiedz

5

Otrzymasz nakładającą błąd instancji, ponieważ niektóre z wystąpień P mogą mieć inne instancje Show a następnie kompilator nie będzie mógł zdecydować, które z nich korzystać. Jeśli masz instancję P dla Double, to masz dwa wystąpienia: Show dla Double: twój ogólny i ten już zadeklarowany w bibliotece podstawowej Haskella. Sposób wywołania tego błędu jest poprawnie określony przez @augustss w komentarzach do twojego pytania. Aby uzyskać więcej informacji, patrz the specs.

Jak już wiesz, nie ma sposobu, aby osiągnąć to, czego próbujesz, bez numeru UndecidableInstances. Po włączeniu tej flagi musisz zrozumieć, że przejmujesz odpowiedzialność kompilatora, aby upewnić się, że nie wystąpią żadne sprzeczne instancje. Oznacza to, że w Twojej bibliotece nie mogą być inne instancje. Oznacza to również, że twoja biblioteka nie wyeksportuje klasy P, co spowoduje skasowanie możliwości użytkowników biblioteki deklarującej sprzeczne instancje.

Jeśli twoja sprawa jest w jakiś sposób sprzeczna z powyższym, jest to niezawodny znak, że coś musi być z tym nie tak. I faktycznie jest ...


Co próbujesz osiągnąć, jest nieprawidłowe przede wszystkim. Brakuje kilka ważnych punktów o Show typeclass, odróżniając ją od konstrukcji jak toString metody popularnych języków OO

  1. Od Show's haddock:

    Wynik show jest składniowo poprawne wyrażenie Haskell zawierające tylko stałe, biorąc pod uwagę deklaracje utrwalenia obowiązujące w miejscu, w którym zadeklarowano typ. Zawiera tylko nazwy konstruktorów zdefiniowane w typie danych, nawiasach i spacjach.Gdy używane są pola oznaczone etykietami konstruktora, używane są również nawiasy klamrowe, przecinki, nazwy pól i znaki równości.

    Innymi słowy, zgłoszenie instancji Show, które nie generuje prawidłowego wyrażenia Haskella, jest niepoprawne jako takie.

  2. Biorąc pod uwagę powyższe, po prostu nie ma sensu zadeklarować niestandardowego wystąpienia Show, gdy typ pozwala go po prostu wyprowadzić.

  3. Gdy typ nie pozwala na wyprowadzenie go (np. GADT), zazwyczaj trzeba będzie trzymać się instancji specyficznych dla określonego typu, aby uzyskać poprawne wyniki.

Tak więc, jeśli potrzebujesz niestandardowej funkcji reprezentacji, nie powinieneś używać do tego celu Show. Po prostu zadeklaruj niestandardową klasę, np .:

class Repr a where 
    repr :: a -> String 

i odpowiedzialnie podejdź do deklaracji instancji.

+0

Jestem nieufny, aby zaakceptować tę odpowiedź, ponieważ uważam, że jest to częściowo niewłaściwe z technicznego punktu widzenia. Problem nie polega na tym, że niektóre instancje 'P' mają inne instancje' Show': jak zauważono, tam * nie ma * żadnych instancji 'P'. 'augustss' wyjaśnił prawdziwy problem związany z oceną nakładania się. Jeśli to naprawisz, chętnie zaakceptuję; Rozważam użycie "show". – Impredicative

+0

@Impredicative Prawdopodobnie nie wyjaśniłem się, zaktualizowałem pierwszy akapit. –