Вы можете использовать значение, которое не определено до тех пор, пока не будет получен результат вычисления при построении данных в вычислении с помощью завязывание рекурсивного узла.
Следующее вычисление создает список значений, каждое из которых содержит общее количество элементов в списке, несмотря на то, что общее количество вычисляется той же функцией, которая строит список. Привязка 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)]
Эту идею можно применить к алгоритму Укконена, передав #
, которые неизвестны, пока не будет известен весь результат.
Общая идея рекурсивной передачи результата в функцию называется наименьшей фиксированной точкой и реализована в 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
person
Cirdec
schedule
27.12.2014
ST
иSTRef
s. Затем вы можетеrunST
получить свое чистое дерево суффиксов в конце. - person chi   schedule 27.12.2014