Ocaml 中的 List.Fold_Left 类型系统?
Posted
技术标签:
【中文标题】Ocaml 中的 List.Fold_Left 类型系统?【英文标题】:List.Fold_Left type system in Ocaml? 【发布时间】:2012-09-29 07:08:36 【问题描述】:编写一个 Ocaml 函数 list_print : string list -> unit
从左到右打印列表中的所有字符串:
所以假设我有一个 Ocaml 函数list_print: string list -> unit
,它打印列表中的所有字符串,从左到右写入。现在正确的解决方案是:
let list_print lst = List.fold_left (fun ( ) -> fun s -> print_string s) () lst;;
但是在编写我的解决方案时,我是这样写的:
let list_print lst = List.fold_left (fun s -> print_string s) () lst;;
但这给了我
错误:此表达式的类型为 unit,但表达式的类型应为 'a -> string
为什么我需要第一个参数 fun() -> 在 fun 之前?我还是 Ocaml 的新手,所以这种类型系统让我很困惑
【问题讨论】:
【参考方案1】:fold_left
(和fold_right
)的目的是在你前进的过程中积累一个价值。额外的参数就是这个累加值。
您可以使用List.iter
解决您的问题。它不累积值。
您可以将List.iter
视为List.fold_left
的一个版本,它累积unit
类型的值。而且,事实上,您可以这样实现它:
let iter f = List.fold_left (fun () a -> f a) ()
重点(与 unit
一样)是该类型只有一个值,因此它表示该值不感兴趣的情况。
【讨论】:
【参考方案2】:您想使用List.fold_left
,这很好,但您应该从阅读该函数的文档开始。官方文档很短:
val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
List.fold_left f a [b1; ...; bn] is f (... (f (f a b1) b2) ...) bn.
首先是那个函数的类型。类型是
('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
换句话说,函数fold_left
具有三个参数和一个结果值。第一个参数的类型为('a -> 'b -> 'a)
。第二个参数的类型为'a
。第三个参数的类型为'b list
。函数的结果值类型为'a
。
现在,在您的情况下,您想要 打印 字符串。所以你实际上不需要任何结果值,你需要一个副作用。但是,在 OCaml 中,所有函数都必须有一个结果值。因此,您使用空值()
,其类型为unit
。因此,在您的情况下,类型参数 'a
将等于 unit
。
类型参数'b
是string
,因为您需要处理字符串列表。
因此,在您的情况下,函数fold_left
必须具有类型
(unit -> string -> unit) -> unit -> string list -> unit.
fold_left
的第一个参数必须是 unit->string->unit
类型。换句话说,它必须是一个有两个参数的函数,第一个参数是空值,即()
,第二个参数是一个字符串。所以fold_left
的第一个参数必须是这种函数,
fun x y -> ...
其中x
必须是unit
类型和y
类型string
。由于x
将始终等于()
,因此没有必要将此参数写为变量x
,而是我们可以简单地写为()
甚至是虚拟参数_
。 (语法fun x -> fun y -> ...
提供与fun x y -> ...
相同的功能。)
现在您可以开始弄清楚 fold_left 是如何工作的。既然这显然是一道作业题,我就把这个任务留给你。
【讨论】:
以上是关于Ocaml 中的 List.Fold_Left 类型系统?的主要内容,如果未能解决你的问题,请参考以下文章