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单元格已经被计算,因为它的值必须是
空的
节点
,而不进行计算