Haskell-编写在Trie结构中搜索和计数的函数

Haskell-编写在Trie结构中搜索和计数的函数,haskell,Haskell,以下是在我的代码中声明Trie数据结构的方式: data Trie = MakeTrie Char [Trie] 现在我必须编写一个名为countChar的函数,它接收一个Trie和一个目标值(Char类型),并计算目标值在Trie中出现的次数 这是我写的代码: countChar :: Trie -> Char -> Integer countChar (MakeTrie root []) target | root == target = 1 | otherw

以下是在我的代码中声明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

但是我认为这样做不正确,现在我或多或少不知道如何使函数工作。

如果您可以将方法的签名更改为
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))
这样,您可以使用
Trie
列表中的
map


例如,给定
countChar'A'(MakeTrie'A'[MakeTrie'B'[MakeTrie'A'[]],MakeTrie'C'[]])
它将返回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))
这样,您可以使用
Trie
列表中的
map

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

定义
Trie
的一种稍微有趣的方法是

type Trie = Cofree [] Char
这为我们免费提供了一个可折叠的
实例,因为
[]
是可折叠的。我们还可以在
Trie
的数据decl中添加一个
deriving Foldable

这意味着我们可以做到:

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~Char
t~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)
这个故事的寓意是:利用类型类和其他现有机制绕过样板文件并概括您的代码。

定义
Trie
更“有趣”的方法是

type Trie = Cofree [] Char
这为我们免费提供了一个可折叠的
实例,因为
[]
是可折叠的。我们也可以只向数据decl中添加一个
派生可折叠的
,用于
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~Char
t~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)

这个故事的寓意是:利用类型类和其他现有机制绕过样板文件并概括您的代码。

如果您可以将签名更改为
countChar::Char->Trie->Integer
您可以做
sum(map(countChar目标)children))
@moondaisy谢谢,我会试试你的suggestion@moondaisy嗯…它编译不正确。这是你的建议吗?countChar(MakeTrie根子级)target=sum(map(countChar target)子项,如果您可以将签名更改为
countChar::Char->Trie->Integer
您可以执行
sum(map(countChar target)子项))
@moondasi谢谢,我将尝试您的suggestion@moondaisy嗯…它编译不正确。这是你的建议吗?countChar(MakeTrie root children)target=sum(map(countChar target)children)回答得很好,虽然它可能比我们期望知道的Haskell类型更高级哈哈。回答得很好,尽管它可能比我们期望知道的Haskell类型更高级哈哈。