Ocaml 这两个懒惰类型定义之间的区别是什么?
我看不出有什么不同 我唯一能确定的是,在Ocaml 这两个懒惰类型定义之间的区别是什么?,ocaml,lazy-evaluation,Ocaml,Lazy Evaluation,我看不出有什么不同 我唯一能确定的是,在2nd类型中,即使是空的也会被放进一个懒洋洋的thunk,对吗?如果我是对的,那么把空的放到thunk的目的是什么 还有其他区别吗 编辑 我在问两种类型的列表之间的区别:list\u t和zlist\u t我认为,第一种类型的问题是节点(foo,lazy-Empty)不能用lazy.t来包装foo本身的计算 让我用两个例子再解释一下: type 'a list_t = | Empty | Node of 'a * 'a list_t la
2nd
类型中,即使是空的
也会被放进一个懒洋洋的thunk,对吗?如果我是对的,那么把空的放到thunk的目的是什么
还有其他区别吗
编辑
我在问两种类型的列表之间的区别:list\u t
和zlist\u t我认为,第一种类型的问题是节点(foo,lazy-Empty)
不能用lazy.t
来包装foo
本身的计算
让我用两个例子再解释一下:
type 'a list_t =
| Empty
| Node of 'a * 'a list_t lazy_t
type 'a node_t =
| Empty
| Node of 'a * 'a zlist_t
and 'a zlist_t = 'a node_t lazy_t
这里,'a
元素的评估在我构建列表之前就已经执行了。换句话说,您编写的第一个类型定义是始终计算其head元素的列表的定义。相反,第二个定义并不强制您计算列表的头部以构建它
# type 'a list_t = Empty | Node of 'a * 'a list_t lazy_t;;
type 'a list_t = Empty | Node of 'a * 'a list_t lazy_t
# Node ((print_endline "hello"; 1), lazy Empty);;
hello
- : int list_t = Node (1, lazy Empty)
我认为第一个的问题是,节点(foo,lazy-Empty)
不能包装在lazy.t
中,从而使foo
本身的计算变得懒惰
让我用两个例子再解释一下:
type 'a list_t =
| Empty
| Node of 'a * 'a list_t lazy_t
type 'a node_t =
| Empty
| Node of 'a * 'a zlist_t
and 'a zlist_t = 'a node_t lazy_t
这里,'a
元素的评估在我构建列表之前就已经执行了。换句话说,您编写的第一个类型定义是始终计算其head元素的列表的定义。相反,第二个定义并不强制您计算列表的头部以构建它
# type 'a list_t = Empty | Node of 'a * 'a list_t lazy_t;;
type 'a list_t = Empty | Node of 'a * 'a list_t lazy_t
# Node ((print_endline "hello"; 1), lazy Empty);;
hello
- : int list_t = Node (1, lazy Empty)
没有区别'a zlist\u t
是节点的别名。执行替换后,我们最终得到:
# match Lazy.force x with Empty -> () | Node _ -> ();;
hello
- : unit = ()
键入“a节点”=
|空的
|“a*”的节点a节点
你能做的是:
type 'a node_t =
| Empty
| Node of 'a * 'a node_t lazy_t
键入“a节点”=
|空的
|('a*'a节点)惰性节点
或许最好写为:
type 'a node_t =
| Empty
| Node of ('a * 'a node_t) lazy_t
键入“a”节点=
|空的
|“z列表”的节点
和'a zlist=('a*'a node)lazy\t
请注意,由于OCaml 3.08左右,我们可以在模式匹配期间强制计算惰性表达式,如下所示:
type 'a node =
| Empty
| Node of 'a zlist
and 'a zlist = ('a * 'a node) lazy_t
匹配
|空->。。。
|节点(惰性(…,…)->
不要使用这个定义。最好让列表完全像你定义的那样懒惰。如果您愿意,您可以独立地将列表中的元素设置为惰性。没有区别'a zlist\u t
是节点的别名。执行替换后,我们最终得到:
# match Lazy.force x with Empty -> () | Node _ -> ();;
hello
- : unit = ()
键入“a节点”=
|空的
|“a*”的节点a节点
你能做的是:
type 'a node_t =
| Empty
| Node of 'a * 'a node_t lazy_t
键入“a节点”=
|空的
|('a*'a节点)惰性节点
或许最好写为:
type 'a node_t =
| Empty
| Node of ('a * 'a node_t) lazy_t
键入“a”节点=
|空的
|“z列表”的节点
和'a zlist=('a*'a node)lazy\t
请注意,由于OCaml 3.08左右,我们可以在模式匹配期间强制计算惰性表达式,如下所示:
type 'a node =
| Empty
| Node of 'a zlist
and 'a zlist = ('a * 'a node) lazy_t
匹配
|空->。。。
|节点(惰性(…,…)->
不要使用这个定义。最好让列表完全像你定义的那样懒惰。如果愿意,您可以独立地始终使列表中的元素变为惰性。在'节点
和'列表
之间绝对没有区别,因为您可以将别名'a zlist\t
的定义替换为'a node\u t
的定义,您得到的与'a list\t
完全类似
你说你在问'a list\u t
和'a zlist\u t
之间的区别。嗯,'a zlist\u t
只是'a node\u t lazy\u t
的类型别名。如上所述,节点
和列表
是等价的,这意味着一个zlist
,即一个节点
相当于一个列表
所以你的问题基本上是问列表与列表的区别是什么
嗯,从外观上看,区别很简单——一个是另一个包装在lazy\t
中,这意味着它是另一个的懒惰版本。如果您有一个类型为“a list\u t
”的值,这意味着第一个cons单元格已经被计算,因为它的值必须是空的
或节点
,而不计算惰性表达式。此外,如果它是节点
,则还必须对第一项进行求值,因为它位于节点
内,没有延迟
。另一方面,如果您有一个类型为'a list\u t lazy\u t
的值,这意味着第一个cons单元格可能不会被计算;除非你强制执行,否则你不会得到一个“列表”
。节点和“列表”
之间绝对没有区别,因为您可以将别名'a zlist\t
的定义替换为'a node\u t
的定义,您得到的与'a list\t
完全类似
你说你在问'a list\u t
和'a zlist\u t
之间的区别。嗯,'a zlist\u t
只是'a node\u t lazy\u t
的类型别名。如上所述,节点
和列表
是等价的,这意味着一个zlist
,即一个节点
相当于一个列表
所以你的问题基本上是问列表与列表的区别是什么
嗯,从外观上看,区别很简单——一个是另一个包装在lazy\t
中,这意味着它是另一个的懒惰版本。如果您有一个类型为'a list\u t
的值,这意味着第一个cons单元格已经被计算,因为它的值必须是空的
或节点
,而不进行计算