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.