Seq展开是如何实现的
How is Seq unfold implemented
请问Seq的展开功能是如何实现的
我尝试创建自己的 Seq 模块 (My_Seq) 以查看我是否了解该功能的工作原理,但我无法让展开的行为像 Seq 的展开功能一样。
这是我的尝试(My_Seq,请注意我删除了除必要功能以外的所有功能)
module type My_Seq_Sig =
sig
type 'a t
val empty: 'a t
val iter: ('a -> unit) -> 'a t -> unit
val unfold : ('b -> ('a * 'b) option) -> 'b -> 'a t
end
module My_Seq:My_Seq_Sig =
struct
type 'a t = unit -> 'a node
and
'a node =
| Nil
| Cons of 'a * 'a t
let empty = fun () -> Nil
let rec iter f s =
match s() with
| Nil -> ()
| Cons (e, next) -> f e; iter f next
let rec unfold f e =
match (f e) with
| None -> empty
| Some (e, next) -> fun () -> Cons (e, unfold f next)
end
下面是我如何调用我的模块 My_Seq:
let seq =
let line = ref 0 in
let filename = print_string "Enter filename: "; read_line() in
My_Seq.unfold
(
fun e ->
try
line := !line + 1;
Some(((string_of_int !line) ^ ": " ^ (input_line e)), e)
with
End_of_file
| _ ->
print_endline("---Read->" ^ string_of_int (!line - 1) ^ "<-Line(s)---");
close_in e;
None
)
(open_in filename)
let () =
seq |> My_Seq.iter print_endline
这是我尝试的结果:
Enter filename: datafile
1: This is the first
2: This is the second
3: This is the third
4: This is the fourth
---Read->5<-Line(s)---
5: This is the fifth
现在如果我使用 Seq 的展开功能:
let seq2 =
let line = ref 0 in
let filename = print_string "Enter filename: "; read_line() in
Seq.unfold
(
fun e ->
try
line := !line + 1;
Some(((string_of_int !line) ^ ": " ^ (input_line e)), e)
with
End_of_file
| _ ->
print_endline("---Read->" ^ string_of_int (!line - 1) ^ "<-Line(s)---");
close_in e;
None
)
(open_in filename)
let () =
seq2 |> Seq.iter print_endline
这是使用 Seq 的展开函数的输出:
Enter filename: datafile
1: This is the first
2: This is the second
3: This is the third
4: This is the fourth
5: This is the fifth
---Read->5<-Line(s)---
数据文件内容:
This is the first
This is the second
This is the third
This is the fourth
This is the fifth
您会注意到输出不同,我不知道为什么。也许有人可以阐明这一点。
做到了 Guest0x0
let rec unfold f e =
fun () ->(
match (f e) with
| None -> Nil
| Some (e, next) -> Cons (e, unfold f next))
区别在于计算最后一个元素的时间。在你的 unfold
中,当元素 before 被获取(通过在某处提供一个单元参数)时,计算最后一个元素(在 f e
中),而 Stdlib
版本仅在获取最后一个元素时才计算该元素本身。
为了让你的 unfold
表现得像 Stdlib
一样,请注意你的 unfold
returns 的两个分支都是一个以单位为参数的函数。通过将此参数提升到整个模式匹配之外,f e
的实际计算将被延迟,从而导致 Stdlib
行为
请问Seq的展开功能是如何实现的
我尝试创建自己的 Seq 模块 (My_Seq) 以查看我是否了解该功能的工作原理,但我无法让展开的行为像 Seq 的展开功能一样。
这是我的尝试(My_Seq,请注意我删除了除必要功能以外的所有功能)
module type My_Seq_Sig =
sig
type 'a t
val empty: 'a t
val iter: ('a -> unit) -> 'a t -> unit
val unfold : ('b -> ('a * 'b) option) -> 'b -> 'a t
end
module My_Seq:My_Seq_Sig =
struct
type 'a t = unit -> 'a node
and
'a node =
| Nil
| Cons of 'a * 'a t
let empty = fun () -> Nil
let rec iter f s =
match s() with
| Nil -> ()
| Cons (e, next) -> f e; iter f next
let rec unfold f e =
match (f e) with
| None -> empty
| Some (e, next) -> fun () -> Cons (e, unfold f next)
end
下面是我如何调用我的模块 My_Seq:
let seq =
let line = ref 0 in
let filename = print_string "Enter filename: "; read_line() in
My_Seq.unfold
(
fun e ->
try
line := !line + 1;
Some(((string_of_int !line) ^ ": " ^ (input_line e)), e)
with
End_of_file
| _ ->
print_endline("---Read->" ^ string_of_int (!line - 1) ^ "<-Line(s)---");
close_in e;
None
)
(open_in filename)
let () =
seq |> My_Seq.iter print_endline
这是我尝试的结果:
Enter filename: datafile
1: This is the first
2: This is the second
3: This is the third
4: This is the fourth
---Read->5<-Line(s)---
5: This is the fifth
现在如果我使用 Seq 的展开功能:
let seq2 =
let line = ref 0 in
let filename = print_string "Enter filename: "; read_line() in
Seq.unfold
(
fun e ->
try
line := !line + 1;
Some(((string_of_int !line) ^ ": " ^ (input_line e)), e)
with
End_of_file
| _ ->
print_endline("---Read->" ^ string_of_int (!line - 1) ^ "<-Line(s)---");
close_in e;
None
)
(open_in filename)
let () =
seq2 |> Seq.iter print_endline
这是使用 Seq 的展开函数的输出:
Enter filename: datafile
1: This is the first
2: This is the second
3: This is the third
4: This is the fourth
5: This is the fifth
---Read->5<-Line(s)---
数据文件内容:
This is the first
This is the second
This is the third
This is the fourth
This is the fifth
您会注意到输出不同,我不知道为什么。也许有人可以阐明这一点。
做到了 Guest0x0
let rec unfold f e =
fun () ->(
match (f e) with
| None -> Nil
| Some (e, next) -> Cons (e, unfold f next))
区别在于计算最后一个元素的时间。在你的 unfold
中,当元素 before 被获取(通过在某处提供一个单元参数)时,计算最后一个元素(在 f e
中),而 Stdlib
版本仅在获取最后一个元素时才计算该元素本身。
为了让你的 unfold
表现得像 Stdlib
一样,请注意你的 unfold
returns 的两个分支都是一个以单位为参数的函数。通过将此参数提升到整个模式匹配之外,f e
的实际计算将被延迟,从而导致 Stdlib
行为