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