Наложение структуры данных?
-
26-10-2019 - |
Вопрос
У меня есть вложенный, взаимный рекурсивный структура данных, и хотите связать с некоторыми узлами значения, требующие больших вычислительных затрат.На самом деле, я хочу временно связать блоки в Пандок document в список слов, встречающихся в этом блоке.
Непривлекательные варианты, которых я хочу избежать:
расширение типа данных Block таким образом, чтобы он включал список слов, что сводится к созданию нового расширенного типа данных Pandoc с большим количеством (хрупкого) шаблонного кода.
сопоставление блоков со списками слов;что неоптимально, поскольку блоки слишком сложны, чтобы эффективно служить ключами.
Направление, в котором я ищу решение, — это некая наложенная структура данных, включающая расширенные блоки, но с нетронутыми базовыми типами данных, чтобы я мог по-прежнему использовать обширные библиотеки Pandoc.Но, возможно, это не образ мышления Haskell...
Постскриптум 12 июня 2011 г.:
Как показывают комментарии, я, вероятно, переоценил стоимость подхода Map, частично основываясь на неверных предположениях.Действительно:«Нет ничего более обманчивого, чем очевидный факт».
В любом случае, я принимаю ответ Хаммара, потому что он иллюстрирует, как создать расширяемый тип данных.
Спасибо
Решение
Вы не можете добавлять что-либо к существующему типу данных, если он не предназначен для расширения, поэтому вам придется полагаться на некоторую внешнюю структуру, например Map
связать списки слов с каждым блоком.
Однако если бы вы могли изменить тип данных, вы могли бы сделать его расширяемым, обобщив рекурсию в типе данных.Допустим, у вас есть такой рекурсивный тип данных:
data Tree = Leaf | Fork String Tree Tree
Мы можем добавить параметр для рекурсивного использования Tree
:
data GenTree t = Leaf | Fork String t t
Теперь, чтобы получить простое дерево, подобное оригиналу, мы возьмем фиксированную точку такого типа:
data Fix a = Fix (a (Fix a))
type Tree = Fix GenTree
Теперь вы можете расширить тип дополнительными данными на каждом рекурсивном сайте.Вот как создать тип для помеченных деревьев:
data Labelled t = Labelled Int (GenTree t)
type LabelledTree = Fix Labelled
strLength :: GenTree t -> Int
strLength Leaf = 0
strLength (Fork str _ _) = length str
label :: Tree -> LabelledTree
label (Fix tree) = Fix $ Labelled (strLength tree) (fmap label tree)
instance Functor GenTree where
fmap f Leaf = Leaf
fmap f (Fork s l r) = Fork s (f l) (f r)