Так что, если у меня есть два типа данных, которые в основном одинаковы, я могу написать их так:
data A t = A1 | A2 | A3 | A4 (B t)
data B t = B1 | B2 | B3 | B4 t
type AX = A X
type AY = A Y
Теперь легко писать функции через AX и AY или 'A t', если онине волнуетНо тогда как мне написать преобразование?
convert :: AX -> AY
convert (A4 (B4 x)) = A4 (B4 (xToY x))
convert ax = ay -- type error
Так что теперь мне нужно выписать все остальные случаи вручную, хотя ни один из них не зависит от параметра типа.Что еще хуже, хотя я могу сопоставить конструктор, не завися от аргументов с помощью 'A {}', это невозможно, если мне нужны эти аргументы для восстановления данных.
Есть ли более хороший способ сделать это?Я чувствую, что GADT должен быть в состоянии выразить это, но трудно понять, как исключить переменную типа из терминов, которые от нее не зависят.Я думаю, что я должен был бы иметь отдельные типы для A1 A2 и т. Д., И тогда я бы потерял закрытость и проверку регистра ... кроме того, я не хочу писать Show, Eq и Typeable вручную!Единственный другой способ, который я могу придумать, - это перестроить всю структуру, чтобы изолировать изменяющуюся часть, т.е.
data A t = Independent | B4 t
data Independent = A1 | A2 | ...
Но это затрудняет любое другое использование данных в пользу одной функции преобразования.
Конечно, еще один вариант - забыть о безопасности типов и включить 'B4 (Either XY)' и добавить несколько приятных ошибок времени выполнения, когда оно имеет неправильное значение.
Может быть, есть лучший способприблизиться к «почти одинаковым» типам данных?
Обновление: поэтому я обошел стороной, написав псевдо-fmap:
convert :: (a -> b) -> A a -> A b
, который, по крайней мере, позволяет мне отделить часть преобразования иупаковка-распаковка.Я предполагаю, что достаточно продвинутая часть TH могла бы сгенерировать одну из них для меня.Мне все еще интересно о других подходах, хотя.Я чувствую, что этот способ все еще не точен, потому что он позволяет заполнить отверстие чем-либо , в то время как на самом деле я имею в виду только одну из двух вещей.