Haskell: определения экземпляров для семейств типов
Допустим, у нас есть следующий код:
<code>class C t where g :: t instance C Int where g = 42 </code>
Просто. Мы также можем определить функции на Int, например, так:
<code>f1 :: Int -> Int f1 x = x * x </code>
Я работал с семействами типов, в частности потому, чтоData.Has
использует их, и я хочу вставить их вIxSet
.
Но здесь я собираюсь представить упрощенный пример. Допустим, мы хотим определить новый типX
, что похоже на Int. Мы могли бы сделать это:
<code>type family X type instance X = Int </code>
Затем мы можем определить функции наX
вот так:
<code>f2 :: X -> X f2 x = x * x + 1 </code>
Пока проблем нет. Теперь давайте попробуем определить экземплярC X
как мы сделали дляC Int
:
<code>instance C X where g = 43 </code>
Ой, теперь у нас есть следующая ошибка:
Illegal type synonym family application in instance: X
In the instance declaration for 'C X'
Теперь давайте попробуем что-то немного другое:
<code>newtype NewX = NewX X instance C NewX where g = 43 </code>
Теперь у нас есть другая ошибка, а именно:
No instance for (Num NewX)
arising from the literal '43'
Кажется, чтоnewtype
Ключевое слово исключает любую информацию о том, к каким классам принадлежал предыдущий класс. Однако, кажется, что я не могу избежатьnewtype
, поскольку я не могу использовать семейства типов в определениях экземпляров.
Есть ли лучший способ сделать это без необходимости переписывать определения экземпляров с дополнительными явными упоминаниями экземпляров, которые в противном случае были бы выведены?
Background information:
Причина, по которой мне нужно это работает, заключается в следующем:
<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>
Это не с:
Illegal type synonym family application in instance: Row
In the instance declaration for 'Indexable Row'
ИзготовлениеRow
newtype
вызывает следующую ошибку:
No instance for (Contains (Labelled Col1 Text) Row) arising from a use of `^.' Possible fix: add an instance declaration for (Contains (Labelled Col1 Text) Row)
Единственный способ, которым я могу обойти это, - это добавить длинное производное предложение следующим образом:
<code>newtype Row = Row (FieldOf Col1 :&: FieldOf Col2) deriving ( Contains (Labelled Col1 Text), -- Add this for every column Contains (Labelled Col2 Text) -- ... ) </code>
Даже то, что позволяет мне "typedef"Contains (Labelled x (TypeOf x))
сказатьHasCol x
было бы полезно.