2013-05-08 3 views
7

Ich verwende den folgenden typeclass:Wie kann man Haskell mitteilen, nicht dieselbe Instanz von zwei Modulen zu importieren?

module T where 
class T a where 
    v :: a 

Eine Instanz T Int, die ich umgesetzt:

import T 
import A (av) 

instance T Int where 
    v = 0 

main = putStrLn (av ++ show v) 

Und ein Modul, das ich von Wert verwenden möchten, die auch eine Instanz hat von T Int.

module A where 
import T 
instance T Int where 
    v = 0 
av = "value from A" 

Das Problem ist, das nicht funktioniert:

$ runghc Main.hs 

Main.hs:4:9: 
    Duplicate instance declarations: 
     instance T Int -- Defined at Main.hs:4:9-13 
     instance T Int -- Defined at A.hs:3:9-13 

Haskell beklagt, dass es 2 Erklärungen für die gleiche Instanz. Wie kann ich ihm mitteilen, dass er die Instanz nicht von B importieren oder beide Instanzen vereinheitlichen oder nur die Instanz von Main verwenden soll?

+1

Tun Sie das nicht. Die richtige Lösung besteht darin, die Instanz nur an einer Stelle zu deklarieren. – hammar

+0

@hammar: Ich habe 'T' oder' B' nicht geschrieben, aber ich möchte einen Wert von 'B' verwenden, und ich möchte eine Instanz von' T' machen. – Dog

+1

Ah, das macht es schwieriger. In diesem Fall können Sie einen 'newtype' erstellen, der den vorhandenen Typ umschließt, und stattdessen Ihre Instanz für den' newtype' schreiben. – hammar

Antwort

8

Leider können Sie nicht steuern, wie Instanzen importiert und exportiert werden. siehe Do Haskell imports have side effects?.

Dies bedeutet, dass Sie Ihren Code umgestalten müssen, um sicherzustellen, dass die Instanz nur in einer Datei definiert ist. Im Allgemeinen ist es am besten, nur eine Instanz in der Datei zu definieren, die entweder die Klasse oder den Datentyp definiert - tatsächlich gibt es sogar eine Warnung über "verwaiste" Instanzen, die dieser Regel nicht folgen. (Betrachten Sie Orphaned instances in Haskell für eine lange Diskussion darüber, warum Sie verwaiste Instanzen vermeiden sollten.) Wenn dies jedoch aus irgendeinem Grund nicht möglich ist, können Sie immer noch beliebig eine der Dateien auswählen, um sie zu behalten oder sogar ein neues Modul zu erstellen von allen Dateien importiert werden, die diese bestimmte Instanz benötigen.

Allgemeiner gesagt, wie würden Sie mit der Möglichkeit befassen, dass die beiden Instanzen verschiedene Dinge tat, wie:

instance T Int where v = 0 
{- And in a different file: -} 
instance T Int where v = 1 

Es gibt wirklich keine unmittelbar offensichtliche Weise diese beiden ohne signifikant zu verändern, wie die Haskell eindeutig zu machen Typklassensystem funktioniert.

Da Sie eine der Instanzen selbst geschrieben haben, entfernen Sie diese einfach. Da es das gleiche wie das vordefinierte ist, importieren Sie das Modul einfach dorthin, wo Sie es benötigen.

+0

"Dies bedeutet, dass Sie Ihren Code umgestalten müssen, um sicherzustellen, dass die Instanz nur in einer Datei definiert ist." Wie kann ich das machen? Ich habe nicht "T" oder "B" geschrieben. – Dog

+0

Oh. Dann ja, es ist schlimm. Aus diesem Grund sollten Sie keine verwaisten Instanzen schreiben. Ich würde einen Fehler damit mit dem Modul einreichen, das die verwaiste Instanz hat - das heißt, derjenige, der die Instanz hat, ohne entweder die Klasse oder den Typ zu definieren. –

+2

@Dog: Eigentlich habe ich dein Problem vielleicht falsch verstanden. Da Sie eine der Instanzen geschrieben haben, löschen Sie diese einfach. Schreibe es für einen 'newtype' wenn du musst. –

Verwandte Themen