Конструктор данных в шаблоне haskell
Я пытаюсь создать кольцо 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 ответ
Документация Template Haskell перечисляет то, что вам разрешено склеивать.
Соединение может произойти вместо
- выражение; сращенное выражение должно иметь тип
Q Exp
- тип; сращенное выражение должно иметь тип
Q Typ
- список объявлений верхнего уровня; сращенное выражение должно иметь тип
Q [Dec]
В обоих случаях $n
Однако вы пытаетесь соединить имя.
Это означает, что вы не можете сделать это, используя цитаты и сращивания. Вам нужно будет создать декларацию, используя различные комбинаторы, доступные в Language.Haskell.TH
модуль.
Я думаю, что это должно быть эквивалентно тому, что вы пытаетесь сделать.
genData :: Name -> Q [Dec]
genData n = fmap (:[]) $ dataD (cxt []) n []
[normalC n [strictType notStrict [t| Integer |]]] []
Да, это немного некрасиво, но вот, пожалуйста. Чтобы использовать это, назовите его новым именем, например
$(genData (mkName "Z5"))