将列表转换为链接列表
我试图在标准ML中将列表转换为单链表(不确定双链表是否可行)。但是,我不确定这是怎么做的,但是到目前为止还是会显示我的尝试。
datatype 'a mlist = Nil
| Cons of 'a * 'a mlist ref
fun listToLL [] = Nil
| listToLL (x::xs) = Cons(x, (ref (listToLL xs)))
我首先在数据类型上创建了一个链接列表,但是我对#ref;'功能。我想避免将链表放入惰性列表中,因此ref允许我明确地将下一个序列作为前一个序列的引用。但问题是这个函数根本没有使用链表数据类型,即使我不使用这个链表定义也能工作。那么我的实现是否正确?
作为一个附带问题,唯一可以将链接列表与惰性列表区分开来的' ref'功能?从他们的数据类型定义来看,这似乎就是这样。
将两个链接列表连接在一起
fun joining (mlpx, mlpy) =
case !mlpx of
Nil => mlpx := mlpy
| Cons(_, mlp) => joining(mlp, mlpy)
fun join (mlpx, mlpy) =
let
val mlp = ref mlpx
in
joining(mlp, mlpy);
!mlp
end;
对于第二个操作,我对第二个连接函数中ref
的需求感到非常困惑。当我处理链表时,我是否希望我处理一个引用,或者我是否处理包含来自内部引用的整个Cons结构?我不明白为什么我们不能单独使用joining
函数,因为它似乎已经足够了。为什么需要在ref
函数中创建join
?
答案 0 :(得分:1)
我首先在数据类型上创建了一个链接列表,但是我对#ref;'功能。我想避免将链表放入惰性列表[...]
[...]
作为一个附带问题,唯一可以将链接列表与惰性列表区分开来的' ref'功能?
懒惰列表完全不同,因为它们需要"暂停"计算,通常通过创建闭包(例如,参见this answer以获取SML中的惰性列表的实现)。你的实现并不懒惰。 ref
的使用只允许可变性。
但问题是这个函数根本没有使用链表数据类型,即使我不使用这个链表定义也能工作。那么我的实现是否正确?
您对listToLL
的实施是正确的。我不确定我理解你对这个问题的其余部分的意思。您的函数 使用链接列表数据类型,因为它使用构造函数Nil
和Cons
。
我对第二个连接功能中的ref需要感到非常困惑。当我处理一个链表时,我是否期望我处理一个引用,或者我是否处理包含来自内部引用的整个Cons结构?
你的困惑很自然。我记得当我第一次尝试在SML中实现可变链接列表时,我对完全相同的问题感到非常困惑。
您提供的join
实现创建了一个额外的引用来干净地处理第一个列表为空的情况,因为帮助函数joining
对'a mlist ref
类型的对象进行操作而不是{ {1}}。但是,可以避免创建这个额外的引用。以下是我将如何做到这一点:
'a mlist
答案 1 :(得分:1)
将列表转换为单链表
SML中的列表已经实现为链接列表。
定义类似
的数据类型时datatype 'a mylist = Nil | Cons of 'a * 'a mylist
您正在使用[]
(nil
)和::
创建一个与内置'列表类型同构的类型( >缺点)。
您的尝试似乎是如何使用引用创建可变链接列表。
我想避免将链表放入惰性列表
正如Sam Westrick所指出的,懒惰列表通常是使用闭包进行的:
datatype 'a lazylist = Nil | Cons of 'a * (unit -> 'a lazylist)
编辑:有关详细信息,请参阅他的example of suspensions [stackoverflow.com]。
不确定双向链表是否可行
可变链接列表和双链表都可以使用引用,但我不建议在SML中使用此方法。如果您需要向前和向后遍历列表,或者如果您需要对其进行更新,则可以使用 zippers 完全在功能上执行此操作:
原始文章在OCaml中有例子,LYAH章节在Haskell中有例子。
我想在标准ML中看到一些很好的例子,但我没有找到任何例子。