现在使用长字符串时,我在Haskell中创建后缀树时遇到了一个相当大的问题。
一些构造算法(作为Ukkonen算法的this版本)需要在节点之间建立链接。这些链接"指向"在树中的节点上。在命令式语言中,例如Java,C#等,由于引用类型,这不是问题。
有没有办法在Haskell中模拟这种行为?或者是否存在完全不同的替代方案?
答案 0 :(得分:2)
您可以使用tying a recursive knot计算结构中计算结果之前未确定的值。
以下计算构建一个值列表,每个值都包含列表中项目的总数,即使总计是由构建列表的相同函数计算的。 let
中的zipCount
绑定将zipWithAndCount
的一个结果作为zipWithAndCount
的第一个参数传递。
zipCount :: [a] -> [(a, Int)]
zipCount xs =
let (count, zipped) = zipWithAndCount count xs
in zipped
zipWithAndCount :: Num n => b -> [a] -> (n, [(a, b)])
zipWithAndCount y [] = (0, [])
zipWithAndCount y (x:xs) =
let (count', zipped') = zipWithAndCount y xs
in (count' + 1, (x, y):zipped')
运行此示例会生成一个列表,其中每个项目包含列表中项目总数的计数
> zipCount ['a'..'e']
[('a',5),('b',5),('c',5),('d',5),('e',5)]
这个想法可以通过传入未知的#
来应用于Ukkonen's algorithm。
递归地将结果传递给函数的一般思想称为最小不动点,并在Data.Function
中通过
fix :: (a -> a) -> a
fix f = let x = f x in x
我们可以在zipCount
和zipWithAndCount
方面以无积分形式撰写fix
。
import Data.Function
zipCount :: [a] -> [(a, Int)]
zipCount = snd . fix . (. fst) . flip zipWithAndCount