编写一个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;;
但这给了我
Error: This expression has type unit but an expression was expected of type 'a -> string
为什么在乐趣之前我需要第一个参数fun() - >?我还是Ocaml的新手,所以这种类型的系统让我很困惑
2 回答
fold_left
(和fold_right
)的目的是在你继续时积累一个值 . 额外参数是此累计值 .你可以使用
List.iter
来解决你的问题 . 它不会累积值 .您可以将
List.iter
视为List.fold_left
的一个版本,它会累积unit
类型的值 . 事实上,你可以这样实现它:这一点(与
unit
一样)是有趣的 .你想使用
List.fold_left
,这很好,但你应该先阅读该功能的文档 . 官方文档非常简短:首先是该功能的类型 . 类型是
换句话说,函数
fold_left
有三个参数和一个结果值 . 第一个参数的类型为('a -> 'b -> 'a)
. 第二个参数的类型为'a
. 第三个参数的类型为'b list
. 函数的结果值的类型为'a
.现在,在您的情况下,您想要打印字符串 . 所以你实际上并不需要任何结果值,你需要副作用 . 但是,在OCaml中,所有函数都必须具有结果值 . 因此,您使用空值
()
,其类型为unit
. 因此,在您的情况下,类型参数'a
将等于unit
.类型参数
'b
是string
,因为您需要处理字符串列表 .因此,在您的情况下,函数
fold_left
必须具有类型fold_left
的第一个参数必须具有unit->string->unit
类型 . 换句话说,它必须是具有两个参数的函数,第一个参数是空值,即()
,第二个参数是字符串 . 所以fold_left
的第一个参数必须是这种函数,其中
x
的类型必须为unit
,y
的类型为string
. 由于x
将始终等于()
,因此不必将此参数写为变量x
,而是可以简单地写入()
甚至是伪参数_
. (语法fun x -> fun y -> ...
提供与fun x y -> ...
相同的功能 . )现在您可以开始弄清楚fold_left的工作原理了 . 由于这显然是一个家庭作业问题,我将把这个任务交给你 .