【问题标题】:List.Fold_Left type system in Ocaml?Ocaml 中的 List.Fold_Left 类型系统?
【发布时间】: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 的新手,所以这种类型系统让我很困惑

【问题讨论】:

    标签: list ocaml fold higher-order-functions


    【解决方案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

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

      因此,在您的情况下,函数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 是如何工作的。既然这显然是一道作业题,我就把这个任务留给你。

      【讨论】:

        猜你喜欢
        • 2012-12-31
        • 1970-01-01
        • 2013-09-13
        • 2015-01-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-29
        相关资源
        最近更新 更多