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.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage