Haskell-编写在Trie结构中搜索和计数的函数
以下是在我的代码中声明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
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类型更高级哈哈。