我想让我的Trie数据结构可折叠。基本数据结构如下所示:
data Trie a = Trie {
value :: Maybe a,
children :: [(Char, Trie a)]
} deriving (Show)
我尝试通过定义foldr来实现Foldable类:
instance F.Foldable Trie where
foldr f z (Trie (Just v) children) =
F.foldr (\a b -> F.foldr f b a) (f v z) children
foldr f z (Trie Nothing children) =
F.foldr (\a b -> F.foldr f b a) z children
这不会编译此错误:
Couldn't match type `a' with `Trie a'
`a' is a rigid type variable bound by
the type signature for foldr :: (a -> b -> b) -> b -> Trie a -> b
at Trie.hs:17:5
Expected type: [(Char, a)]
Actual type: [(Char, Trie a)]
In the third argument of `F.foldr', namely `children'
In the expression:
F.foldr (\ a b -> F.foldr f b a) (f v z) children
但是,如果我将子项类型更改为Map Char (Trie a)
,则可折叠实现无需更改即可运行。为了简单起见,我想保留关联列表。你能解释一下为什么foldr在地图和关联列表上表现不同吗?
答案 0 :(得分:3)
错误是因为您试图折叠键值列表
对,而不是Trie
的列表。你想要做的是忽略Char
键,只是折叠到每个子节点,如此
foldr f z (Trie (Just v) children) =
F.foldr (\(_, a) b -> F.foldr f b a) (f v z) children
foldr f z (Trie Nothing children) =
F.foldr (\(_, a) b -> F.foldr f b a) z children