Типы данных с дырами

Итак, если у меня есть два типа данных, которые в основном одинаковы, я могу записать их так:

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, или ' А если им все равно. Но тогда как мне написать преобразование?

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, вероятно, мог бы сгенерировать один из них для меня. Однако мне все еще любопытны другие подходы. Мне кажется, что этот способ все еще неточен, потому что он позволяет заполнить дыру чем угодно , в то время как на самом деле я имею в виду одно из двух.

5
задан Brian Tompsett - 汤莱恩 22 November 2015 в 15:06
поделиться