Haskell - 编写一个在Trie结构

时间:2017-04-22 01:04:33

标签: haskell

这是在我的代码中声明Trie数据结构的方式:

data Trie = MakeTrie Char [Trie]

现在我必须编写一个名为countChar的函数,它接收一个Trie和一个目标值(Char类型)并计算目标值在Trie中出现的次数。

这是我写的代码:

countChar :: Trie -> Char -> Integer
countChar (MakeTrie root []) target 
    | root == target = 1
    | otherwise = 0
countChar (MakeTrie root children) target 
    | root == target = 1 + ...
    | otherwise = 0 + ...

最初我想做一些像这样映射函数的东西:

...otherwise = 0 + foldr1 (+) (map count children target)
where
count = countChar t c

但是我认为这样做不正常,现在我或多或少都不知道该做什么才能使功能发挥作用。

2 个答案:

答案 0 :(得分:4)

定义Trie的一种稍微“有趣”的方式是

type Trie = Cofree [] Char

这为我们提供了免费Foldable个实例,因为[]Foldable。我们也可以在deriving Foldable的数据转换中添加Trie

这意味着我们可以:

countChar :: (Eq a,Num n,Foldable t) => a -> t a -> n
countChar c = foldr (\c' a -> if c == c' then a + 1 else a) 0

如果您愿意,该类型签名可以专门用于Char -> Trie -> Integer。 (使用a ~ Chart ~ Cofree []n ~ Integer

您也可以使用Sum

实现此目的
countChar :: (Eq a,Num n,Foldable t) => a -> t a -> n
countChar c = getSum . foldMap (\c' -> if c == c' then Sum 1 else Sum 0)

故事的道德:利用类型类和其他现有机制来回避样板并概括你的代码。

答案 1 :(得分:2)

如果您可以将方法的签名更改为countChar :: Char -> Trie -> Integer,那么您可以执行此操作:

countChar :: Char -> Trie -> Integer
countChar target (MakeTrie root children) 
    | root == target = (1 + sum(map (countChar target) children))
    | otherwise = (0 +sum(map (countChar target) children))

这样您就可以在map列表中使用Trie

例如,给定countChar 'A' (MakeTrie 'A' [MakeTrie 'B' [MakeTrie 'A' [] ], MakeTrie 'C' []]),它将返回2.