Некоторое время я искал в Google, но не нашел ответа:
Скажем, у меня есть Tree ADT, который является полиморфным, тип базовой суммы полезной нагрузки и два типа суммы расширения:
--Base.hs
data Tree a = Node a [Tree a] | Empty
data BasePayload = BaseA String | BaseB Int
--Extention1.hs
data Extention1 = Ext1A String String | Ext1B Int
--Extention2.hs
data Extention2 = B | A
Я не могу изменить базовый тип и не знаю, используются ли во время компиляции и сколько типов расширения. Можно ли создать функции, которые работают так:
--Base.hs
type GeneralTree = Tree SomeBoxType
transform :: Tree (SomeBoxType (any | BasePayload)) -> Tree (SomeBoxType any)
--Extention1.hs
transform :: Tree (SomeBoxType (any | Extention1)) -> Tree (SomeBoxType any)
--Extention2.hs
transform :: Tree (SomeBoxType (any | Extention2)) -> Tree (SomeBoxType any)
Возможно ли что-то подобное? Когда я искал, я нашел GADT, который мне не нужен, а также DataKinds и TypeFamilies, которые я не понял на 100%, но не думаю, что здесь поможет. Это полиморфизм строк? Спасибо за вашу помощь.
SomeBoxType
? - person leftaroundabout   schedule 28.07.2017Tree (SomeBoxType (any | Extention2))
? Что вы имеете в виду подany | Extention2
там? Это сигнатура функции, а не объявление данных, и здесь вы используете синтаксис объявления данных. - person Bartek Banachewicz   schedule 28.07.2017Extention2
@leftaroundabout Приложение для преобразования дерева на основе подключаемого модуля, дерево представляет данные, которые находятся в полезной нагрузке. В зависимости от контекста мне нужны дополнительные данные, которые можно преобразовать в базовые данные, поэтому у меня есть плагин, который принимает расширенное определение и преобразует все дополнительные данные в базовые данные. Поскольку базовую программу не следует перекомпилировать для каждого параметра, я не могу изменять базовый ADT, в основном это компилятор. - person Jan van Brügge   schedule 28.07.2017transform:: Tree (SomeBoxType any) -> Tree (SomeBoxType (any without Extention2))
. Меня не очень волнуют типы, потому что это все равно происходит во время выполнения. Теоретическиany -> any
тоже было бы хорошо, я просто хочу сопоставить шаблону типов Extention2 - person Jan van Brügge   schedule 28.07.2017Tree AnnotatedData -> Tree BaseData
? Вы не можете сопоставить шаблон для любого значения, это, по сути, динамическая типизация, которую вы просите. - person Bartek Banachewicz   schedule 28.07.2017Tree AnnotatedData1and2 -> Tree AnnotatedData2
и это со всеми возможными перестановками. Невозможно, потому что я хочу добавить плагины позже, не изменяя все остальные плагины. - person Jan van Brügge   schedule 28.07.2017class CombinesWithBase where combine :: a -> BaseData -> BaseData
. Затем вы можете создать polywrapper для расширений:newtype Polyextension = forall a. CombinesWithBase a => Polyextension a
, сделать его экземпляромCombineWithBase
:instance CombineWithBase Polyextension where combine (Polyextension a) b = combine a b
и, наконец, сохранить их в списке:data ComplexData = CD BaseData [Polyextension]
. Предположительно, это антипаттерн (поэтому это не ответ), но он работал у меня раньше. - person Bartek Banachewicz   schedule 28.07.2017