Haskell: Definicje instancji dla rodzin typów

Powiedzmy, że mamy następujący kod:

<code>class C t where
  g :: t

instance C Int where
  g = 42
</code>

Prosty. Możemy również zdefiniować funkcje na Int, w ten sposób:

<code>f1 :: Int -> Int
f1 x = x * x
</code>

Pracuję z rodzinami typów, w szczególności dlatego, żeData.Has używa ich i chcę je wstawić doIxSet.

Ale tutaj przedstawię uproszczony przykład. Powiedzmy, że chcemy zdefiniować nowy typX, to jest podobne do Int. Możemy to zrobić:

<code>type family X
type instance X = Int
</code>

Możemy wtedy zdefiniować funkcjeX w ten sposób:

<code>f2 :: X -> X
f2 x = x * x + 1
</code>

Jak dotąd żadnych problemów. Teraz spróbujmy zdefiniować instancjęC X, tak jak myC Int:

<code>instance C X where
  g = 43
</code>

Och, teraz mamy następujący błąd:

Nielegalna aplikacja synonimiczna typu rodzinnego na przykład:X
W deklaracji instancji dla'C X'

Teraz spróbujmy czegoś innego:

<code>newtype NewX = NewX X

instance C NewX where
  g = 43
</code>

Teraz mamy inny błąd, a mianowicie:

Nie dla przykładu(Num NewX)
wynikające z dosłownego'43'

Wygląda na tonewtype słowo kluczowe eliminuje wszelkie informacje o tym, do jakich klas należała również poprzednia klasa. Wydaje się jednak, że nie mogę tego uniknąćnewtype, ponieważ nie mogę używać rodzin typów w definicjach instancji.

Czy jest lepszy sposób, aby to zrobić bez konieczności przepisywania definicji instancji z dodatkowymi wyraźnymi przykładami, które w przeciwnym razie byłyby wywnioskowane?

Informacje podstawowe:

Powód, dla którego potrzebuję tego do pracy, jest następujący:

<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>

To się nie udaje z:

Nielegalna aplikacja synonimiczna typu rodzinnego na przykład:Row
W deklaracji instancji dla'Indexable Row'

ZrobienieRow a newtype powoduje następujący błąd:

Brak instancji dla wiersza (Zawiera tekst z etykietą Col1) wynikający z użycia `^. ' Możliwa poprawka: dodaj deklarację instancji dla wiersza (zawiera tekst oznaczony jako Col1)

Jedynym sposobem obejścia tego problemu jest dodanie długiej klauzuli pochodnej w następujący sposób:

<code>newtype Row = Row (FieldOf Col1 :&: FieldOf Col2)
  deriving 
  (
    Contains (Labelled Col1 Text), -- Add this for every column
    Contains (Labelled Col2 Text)  -- ...
  )
</code>

Nawet coś, co pozwala mi na „typedef”Contains (Labelled x (TypeOf x)) powiedziećHasCol x byłoby pomocne.

questionAnswers(2)

yourAnswerToTheQuestion