Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/236.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 惰性与渴望评估和双链接列表构建_List_Haskell_Lazy Evaluation_Eager - Fatal编程技术网

List 惰性与渴望评估和双链接列表构建

List 惰性与渴望评估和双链接列表构建,list,haskell,lazy-evaluation,eager,List,Haskell,Lazy Evaluation,Eager,我睡不着!:) 我已经用Haskell编写了构建双链表的小程序。使其成为惰性计算的基本语言属性(请参阅下面的一组代码)。我的问题是,我能不能在纯函数式语言中通过热切的求值来实现同样的效果?在任何情况下,函数语言必须具备哪些属性才能构建这样的结构(杂质?) 只要一种语言有闭包、lambdas之类的东西,你总是可以模拟懒散。您甚至可以在Java中重写该代码(无需修改变量等),只需将每个“惰性”操作包装为 interface Thunk<A> { A eval(); } int

我睡不着!:)

我已经用Haskell编写了构建双链表的小程序。使其成为惰性计算的基本语言属性(请参阅下面的一组代码)。我的问题是,我能不能在纯函数式语言中通过热切的求值来实现同样的效果?在任何情况下,函数语言必须具备哪些属性才能构建这样的结构(杂质?)


只要一种语言有闭包、lambdas之类的东西,你总是可以模拟懒散。您甚至可以在Java中重写该代码(无需修改变量等),只需将每个“惰性”操作包装为

interface Thunk<A> {
   A eval();  
}
interface Thunk{
A eval();
}

当然,这看起来很糟糕,但这是可能的。

在Prolog的非回溯子集中,可以将其视为纯函数式语言的显式设置,您可以轻松地构建双链接列表。正是引用的透明性使得Haskell很难做到这一点,因为它禁止Prolog显式设置命名的、显式尚未设置的逻辑变量,而是迫使Haskell以扭曲的方式“打结”实现同样的效果。我想

另外,Haskell的惰性计算下的保护递归与Prolog的内置尾部递归模cons方式的开放列表之间并没有太大区别。例如,这里有一个例子。已记忆的共享存储用作通用访问中介,因此可以将先前计算的结果安排为缓存

想想看,如果在设置任何变量或指针后都不重置任何变量或指针,那么可以限制性地使用C作为一种纯函数式语言。您仍然有空指针,就像Prolog有变量一样,它也是显式设置一次的。当然,你可以用它建立双链接列表


所以剩下的唯一问题是,你承认这种set-once语言是纯的吗?

双链表可以在一种渴望的语言中以纯函数的方式实现,就像在单链表上一样。例如,请参见。

您需要一些可更新的东西来获得延迟计算的效果(最多计算一次),否则您将模拟按名称调用。因此,augustus,您的观点是,仅仅闭包和lambdas是不够的?我想他只是指,
eval
的结果需要缓存,因此,thunk不会重新计算,应该多次运行
eval
。我认为双链表的要点是,它不会在遍历时分配新的存储,这与您链接到的代码不同,Dan。在它里面,
prev(next-alist)
alist
不是同一个存储,不同于通常的C,比如说,实现,也不同于上面问题中的Haskell代码,在
let(alist,zlist)=makedlist xs
之后,我们有
prev(next-alist)==alist
next(prev-zlist)==zlist
的意思“相同的实际存储”,或者用Lisp的说法“eq-等效”(当然对于非空的
xs
)@WillNess关于“在遍历时不分配新存储”,这是一个实现细节,需要付出代价。您不能“插入”到不可变的双链接列表中(采用OP给出的样式)不制作整个列表的副本。由于懒惰,通常可以减少复制,但关键是新的双链表不能与旧的双链表共享任何节点。不可变拉链实现允许更多共享,但代价是遍历需要更多存储(但也不是更多,同样是由于分享的能力)@WillNess n.b.Haskell对
eq
-ness没有任何保证。GHC的并行垃圾收集器利用了这一点,实际上可以删除您可能期望存在的共享。这是罕见的,几乎不会影响性能,但是,由于数据不可变,它永远不会影响您的结果。我希望如果相同的名称s使用两次,(指向的指针)相同的值将在每个位置使用:在
中让{this=DLNode prev x next;(next,last)=step this xs}
这是
这是
这是
,对吗?这不是懒惰的意思吗?一个名字-一个(指向一个指针)实体,不是吗?关于插入时的整个列表复制,你是完全正确的。也许在某些情况下,zipper更好,而在其他情况下,DL list更好。但它们仍然不同。此外,如果GHC将从同一变量的两次使用中删除共享,它将如何影响依赖它的各种corecursive定义,例如
fibs=0:scanl(+)1 fibs
?它会工作吗,还是会严重降低效率?检查:)它只返回头部节点,非常简单。
interface Thunk<A> {
   A eval();  
}