SML - 使用延续在 trie 中收集单词
Posted
技术标签:
【中文标题】SML - 使用延续在 trie 中收集单词【英文标题】:SML - collecting words in a trie using continuations 【发布时间】:2012-03-15 18:35:55 【问题描述】:我有一个 数据类型 trie = char 的节点 * (trie ref) 列表 |空的 我想收集trie中的所有单词,使用这两个相互递归的函数:
words_in_trie: trie -> (char list list -> 'a) -> 'a
all_words: trie ref list -> (char list list -> 'a) -> 'a
然后用 fun 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)
我多年来一直坚持这一点,我将不胜感激。
【问题讨论】:
标准 ML per se 没有延续。你是在使用Standard ML of New Jersey'sSMLofNJ.Cont
structure,还是其他地方的类似模块,还是自制的?
使用作为函数的延续 (char list list -> 'a),它将列表列表作为输入,表示到目前为止收集的单词的后缀
【参考方案1】:
由于延续的输入是单词的后缀,你知道在调用下一个延续之后,结果必须更接近于 trie 中的单词列表,并且仍然是单词的后缀。您可以使用它来确定延续应该做的是将下一个字母添加到 trie 之前(给定一个 char 列表列表,它将在列表中的每个 char 列表中添加一个 char)。
fun words_in_trie Empty cont = cont[]
如果您传递的 trie 是 Empty
,那么您在该 trie 中有一个单词,这是一个空字符串。你想要的结果是[""]
。回想一下,最后一个延续将列表中的每个 char list
转换为 string
,因此为了获得该结果,您需要将一个带有空 char list
的列表传递给它以进行转换。
|words_in_trie (Node(c,rl)) cont = (all_words rl (fn r=> cont(c::r)))
回想一下:延续的类型是char list list -> 'a
。 c
是一个char
,所以它不能被添加到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
函数对我来说看起来不错。
【讨论】:
all_words
的第二种情况也不是 CPS 形式。
我知道这是一个很晚的回复,但感谢您的回答!这是一个很大的帮助。以上是关于SML - 使用延续在 trie 中收集单词的主要内容,如果未能解决你的问题,请参考以下文章