Haskell: Instanzdefinitionen für Typfamilien
Nehmen wir an, wir haben den folgenden Code:
<code>class C t where g :: t instance C Int where g = 42 </code>
Einfach. Wir können auch Funktionen auf Int definieren, wie zum Beispiel:
<code>f1 :: Int -> Int f1 x = x * x </code>
Ich habe mit Typfamilien gearbeitet, insbesondere weilData.Has
verwendet sie, und ich möchte sie in eine einfügenIxSet
.
Aber hier werde ich ein vereinfachtes Beispiel präsentieren. Nehmen wir an, wir möchten einen neuen Typ definierenX
, das ist ähnlich wie ein Int. Wir könnten dies tun:
<code>type family X type instance X = Int </code>
Wir können dann Funktionen definierenX
wie so:
<code>f2 :: X -> X f2 x = x * x + 1 </code>
Bisher keine Probleme. Versuchen wir nun, eine Instanz zu definierenC X
, wie wir es gemacht habenC Int
:
<code>instance C X where g = 43 </code>
Oh, jetzt haben wir den folgenden Fehler:
Unzulässige Typ-Synonym-Familienanwendung in Beispiel:X
In der Instanzdeklaration für'C X'
Probieren wir jetzt etwas anderes aus:
<code>newtype NewX = NewX X instance C NewX where g = 43 </code>
Jetzt haben wir einen weiteren Fehler, nämlich:
Keine Instanz für(Num NewX)
aus dem wörtlichen'43'
Es scheint wie dasnewtype
Das Schlüsselwort entfernt alle Informationen darüber, zu welchen Klassen die vorherige Klasse gehörte. Es scheint aber auch, dass ich es nicht vermeiden kannnewtype
, da ich in Instanzdefinitionen keine Typfamilien verwenden kann.
Gibt es eine bessere Möglichkeit, dies zu tun, ohne dass Instanzdefinitionen mit zusätzlichen expliziten Instanzen-Erwähnungen neu geschrieben werden müssen, die ansonsten abgeleitet würden?
Hintergrundinformation:
Der Grund, warum ich das brauche, um zu arbeiten, ist der folgende:
<code>import Data.Has import Data.IxSet data Col1 = Col1; type instance TypeOf Col1 = Text data Col2 = Col2; type instance TypeOf Col2 = Text type Row = FieldOf Col1 :&: FieldOf Col2; instance Indexable Row where empty = ixSet [ixFun $ (\x -> [ Col1 ^. x ]) ] -- Maybe add some more indexes later </code>
Dies schlägt fehl mit:
Unzulässige Typ-Synonym-Familienanwendung in Beispiel:Row
In der Instanzdeklaration für'Indexable Row'
HerstellungRow
a newtype
verursacht den folgenden Fehler:
Keine Instanz für (Contains (Labeled Col1 Text) Row) aufgrund der Verwendung von "^". Mögliche Fehlerbehebung: Hinzufügen einer Instanzdeklaration für die Zeile (Contains (Labeled Col1 Text))
Die einzige Möglichkeit, dies zu umgehen, besteht darin, eine lange Ableitungsklausel wie folgt hinzuzufügen:
<code>newtype Row = Row (FieldOf Col1 :&: FieldOf Col2) deriving ( Contains (Labelled Col1 Text), -- Add this for every column Contains (Labelled Col2 Text) -- ... ) </code>
Sogar etwas, das mir erlaubt, "typedef"Contains (Labelled x (TypeOf x))
sagenHasCol x
Wäre hilfreich.