Автоматическое создание Data.Vector.Unbox со связанными синонимами типов

У меня есть тип данных

newtype Zq q = Zq (IntType q)

где 'q' будет экземпляром класса

class Foo a where
   type IntType a

а «IntType» — это просто базовое представление (, т. е. Int, Integral и т. д. ), связанное с «q».

Я хочу сделать Zq экземпляром Data.Vector.Unbox . В настоящее время мы вручную создаем Unbox, используя около 50 строк тривиального кода, как это предлагается по ссылке выше. В нашем коде мы будем создавать несколько разных типов Unbox, поэтому писать по 50 строк для каждого типа не очень привлекательно.

Я нашел две альтернативы здесь . Одним из вариантов является использование этого пакета , который использует Template Haskell для создания экземпляров Unbox. Код TH будет выглядеть как:

derivingUnbox "Zq"
  [d| instance (Foo q, U.Unbox (IntType q)) => Unbox' (ZqBasic q) (IntType q) |]
  [| \ (Zq x) -> x |]
  [| \ x -> Zq x |]

Проблема в том, что я не могу определить экземпляры, используя синонимы связанных типов(или можно??)

[Связанный вопрос :Почему TypeSynonymInstances , расширение, подразумеваемое FlexibleInstances, не позволяет ассоциированным экземплярам синонимов типов? Это как-то принципиально другой зверь?]

Мое текущее решение этой проблемы состоит в том, чтобы переопределить Zq как

newtype Zq q i = Zq i

а затем добавьте ограничение равенства

i~(IntType q)

в каждом случае с участием (Zq q i ), что не очень элегантно. Мой (рабочий )вывод Unbox становится

derivingUnbox "Zq"
  [d| instance (U.Unbox i, i~IntType q, Foo q) => Unbox' (Zq q i) i |]
  [| \ (Zq x) -> x |]
  [| \ x -> Zq x |]

Я чувствую, что должен быть в состоянии выполнить это, не прибегая к явному раскрытию типа «i». Все, что я сделал, это переместил его из синонима связанного типа в явный параметр с ограничениями равенства. Почему это «фундаментально» другой (и, по-видимому, более безопасный )подход? Есть ли способ избежать добавления параметра типа «i» и при этом получить автоматический вывод Unbox?

Помимо дополнительного параметра типа, у меня возникли проблемы с использованием пакета TH для получения Unbox для (Vector r ), то есть я хочу создать Unbox Vector из Unbox Vectors. Моя попытка что-то вроде:

newtype Bar r = Bar (Vector r)

derivingUnbox "Bar"
  [d| instance (Unbox r) => Unbox' (Bar r) (Vector r) |]
  [| \ (Bar x) -> x |]
  [| \ x -> Bar x |]

но я получаю (множество )ошибок типа:

`basicUnsafeFreeze` is not a (visible) method of class `Data.Vector.Generic.Base.Vector`

Я не уверен, почему он не может найти этот метод, когда он отлично работает для моего типа Zq.


Второй подход, указанный выше , использует расширение GeneralizedNewtypeDeriving. Самая большая проблема, которую я вижу с этим подходом, заключается в том, что у меня есть некоторые фактические данные (, а не Newtype ), которые мне нужно распаковать. Однако, просто используя расширение, я должен написать

newtype Zq q = Zq (IntType q) deriving (Unbox, M.MVector MVector, G.Vector Vector)

или хотя бы

newtype Zq q i = Zq i deriving (Unbox, M.MVector MVector, G.Vector Vector)

Первый приводит к ошибкам:

No instance for (Unbox (IntType q)) arising from the `deriving` clause of a data type declaration
No instance for (M.MVector MVector (IntType q)) ""
No instance for (G.Vector Vector (IntType q)) ""

а второй дает:

No instance for (M.MVector MVector i) ""
No instance for (G.Vector U.Vector i) ""

Я не уверен, почему он не может получить эти экземпляры, поскольку сообщение выше заставляет меня поверить, что это должно быть возможно. Возможно, мне сойдет с рук использование синонима связанного типа с GeneralizedNewtypeDeriving? (Это по-прежнему (, вероятно, )не решает мою проблему, когда мне нужно получить Unbox для 'data's.)

Спасибо за вашу помощь!

6
задан crockeea 9 July 2012 в 17:02
поделиться