首页 文章

Ocaml中的List.Fold_Left类型系统?

提问于
浏览
2

编写一个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 回答

  • 1

    fold_left (和 fold_right )的目的是在你继续时积累一个值 . 额外参数是此累计值 .

    你可以使用 List.iter 来解决你的问题 . 它不会累积值 .

    您可以将 List.iter 视为 List.fold_left 的一个版本,它会累积 unit 类型的值 . 事实上,你可以这样实现它:

    let iter f = List.fold_left (fun () a -> f a) ()
    

    这一点(与 unit 一样)是有趣的 .

  • 8

    你想使用 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 .

    类型参数 'bstring ,因为您需要处理字符串列表 .

    因此,在您的情况下,函数 fold_left 必须具有类型

    (unit -> string -> unit) -> unit -> string list -> unit.
    

    fold_left 的第一个参数必须具有 unit->string->unit 类型 . 换句话说,它必须是具有两个参数的函数,第一个参数是空值,即 () ,第二个参数是字符串 . 所以 fold_left 的第一个参数必须是这种函数,

    fun x y -> ...
    

    其中 x 的类型必须为 unity 的类型为 string . 由于 x 将始终等于 () ,因此不必将此参数写为变量 x ,而是可以简单地写入 () 甚至是伪参数 _ . (语法 fun x -> fun y -> ... 提供与 fun x y -> ... 相同的功能 . )

    现在您可以开始弄清楚fold_left的工作原理了 . 由于这显然是一个家庭作业问题,我将把这个任务交给你 .

相关问题