Конструктор данных в шаблоне haskell - PullRequest
11 голосов
/ 27 сентября 2011

Я пытаюсь создать кольцо Z / n (как обычная арифметика, но по модулю некоторое целое число). Примером экземпляра является Z4:

instance Additive.C Z4 where
  zero = Z4 0
  (Z4 x) + (Z4 y) = Z4 $ (x + y) `mod` 4

И так для кольца. Я хотел бы иметь возможность быстро сгенерировать эти вещи, и я думаю, что способ сделать это с помощью шаблона haskell. В идеале я хотел бы просто пойти $(makeZ 4) и выпустить код для Z4, как я определил выше.

Хотя у меня много проблем с этим. Когда я делаю genData n = [d| data $n = $n Integer], я получаю «ошибку разбора в объявлении data / newtype». Это работает, если я не использую переменные: [d| data Z5 = Z5 Integer |], что должно означать, что я делаю что-то странное с переменными. Я не уверен, что, хотя; Я пытался создать их через newName, но это тоже не сработало.

Может кто-нибудь помочь мне с тем, что здесь происходит?

1 Ответ

13 голосов
/ 27 сентября 2011

В документации Template Haskell перечислены элементы, которые вам разрешено соединять.

Соединение может произойти вместо

  • выражения;объединенное выражение должно иметь тип Q Exp
  • тип;объединенное выражение должно иметь тип Q Typ
  • список объявлений верхнего уровня;объединенное выражение должно иметь тип Q [Dec]

Однако в обоих случаях $n вы пытаетесь соединить name .

Это означает, что вы не можете сделать это, используя цитаты и сращивания.Вам нужно будет создать объявление, используя различные комбинаторы, доступные в модуле Language.Haskell.TH.

Я думаю, это должно быть эквивалентно тому, что вы пытаетесь сделать.

genData :: Name -> Q [Dec]
genData n = fmap (:[]) $ dataD (cxt []) n []
                           [normalC n [strictType notStrict [t| Integer |]]] []

ДаНемного некрасиво, но вот, пожалуйста.Чтобы использовать это, назовите его новым именем, например,

$(genData (mkName "Z5"))
...