SML - 使用continuation在trie中收集单词

时间:2012-02-25 15:51:30

标签: recursion sml trie smlnj continuation

我有一个     datatype trie = char *(trie ref)list |的节点空 我想使用这两个相互递归的函数收集trie中的所有单词:

words_in_trie: trie -> (char list list -> 'a) -> 'a

all_words: trie ref list -> (char list list -> 'a) -> 'a

然后用它来调用它们 有趣的all_entries t = all_words t(fn l => map(fn w => String.implode w)l);

这必须通过延续来完成。我用非延续形式写了它,如下:

fun wt Empty = [[]] 
    |wt (Node(c,rl)) = map (fn (l) => c::l) (aw rl)
and aw [] = []
    |aw [h] = wt (!h)
    |aw (h::t) = (wt (!h))@(aw t)

但我无法弄清楚如何将它们转换为延续形式! 这是我到目前为止所做的,但它不起作用:

fun words_in_trie Empty cont = cont[] 
    |words_in_trie (Node(c,rl)) cont = (all_words rl (fn r=> cont(c::r)))
and all_words [h] cont = words_in_trie (!h) cont
    |all_words (h::t) cont = (words_in_trie (!h) cont)@(all_words t cont)

我已经坚持了很久,我会感激任何帮助。

1 个答案:

答案 0 :(得分:2)

由于对continuation的输入是单词的后缀,你知道在调用下一个continuation之后,结果必须更接近trie中的单词列表,并且仍然是单词的后缀。您可以使用它来确定延续应该做的是在trie之前添加下一个字母(给定一个字符列表列表,它将为字符串中的每个字符列表添加一个字符。)

fun words_in_trie Empty cont = cont[]

如果你传递的特里是Empty,那么你在该特里有一个字,这是一个空字符串。您想要的结果是[""]。回想一下,最后一个延续会将列表中的每个char list转换为string,因此为了获得该结果,您需要为其传递一个空char list的列表,以便进行转换

|words_in_trie (Node(c,rl)) cont = (all_words rl (fn r=> cont(c::r)))

召回:延续的类型是char list list -> 'acchar,因此不能将其r添加到char list list类型。

all_words会返回尝试列表rl中包含的所有单词的列表,您希望将这些单词应用于继续(其中所有字符都包含在trie中)。您必须构建延续,以便除了从节点上的节点前面添加所有字符外,它还会从当前节点预先添加char c。您正在寻找的是这样的:

fn x => cont (map (fn y => c::y) x)

上面的内容会c添加到列表中的每个char list,然后将其传递到下一个续集,然后继续下一个char

您的all_words功能对我来说很合适。