【问题标题】:Appending to list based on condition in OCaml根据 OCaml 中的条件附加到列表
【发布时间】:2016-11-19 18:15:06
【问题描述】:

我正在尝试通过附加到列表来创建唯一列表,但出现此错误。

Error: This expression has type 'a list
       but an expression was expected of type unit

in_list 是一个布尔函数,用于检查值是否在列表中。

if(in_list x seen_list) then print_string("Already found") else seen_list@x in
    List.iter uniq check_list;;

看来我必须为 append 函数修复一些小的语法错误。有什么建议吗?

【问题讨论】:

    标签: list integer append ocaml


    【解决方案1】:

    TL;DR:OCaml 中的列表是不可变的

    根据您的代码,您似乎认为 OCaml 中的列表是可变的,但事实并非如此。因此seen_list@x 计算一个新列表但不会更改seen_list

    您可以将代码更改为

    let uniq seen_list x =
       if in_list x seen_list then
         (Printf.printf: "uniq: %d: Already seen.\n" x; seen_list)
       else x :: seen_list
    in
    List.fold_left uniq [] check_list
    

    uniq 函数将整数列表映射到整数列表而不重复,记录它跳过的条目。

    我猜这段代码显然是用来作为学习材料的,不过你应该知道它很可能实现了Shlemiel the painter's algorithm

    【讨论】:

      【解决方案2】:

      这是类型错误,而不是语法错误。

      OCaml 函数必须始终返回相同类型的结果。现在,当项目在列表中时,您的函数会尝试返回与项目不在列表中时不同的类型。

      具体来说,当项目已经存在时,您的函数调用print_string,它返回()。这称为unit,是一个占位符,表示没有有趣的值。当该项目不存在时,您的函数将返回 'a list 类型的值。几乎可以肯定,您需要做的是在所有情况下都返回一个列表。

      如果不查看更多代码,很难说更多,但处理这种情况的最常用方法是在项目已经存在时返回旧列表,并在项目不存在时返回新的更长的列表.

      更新

      这段代码中有很多东西需要修复,但这是我假设练习的重点。

      您的下一个问题似乎是List.iter 是一个命令式函数,即它想要 某事而不是产生结果。因此,它在列表上迭代的函数应该返回 unit(如上所述)。您使用的是函数uniq,它返回一个列表。

      如果你想使用像List.iter这样优秀的OCaml风格的高阶函数,你需要使用折叠(List.fold_leftList.fold_right),其目的是累积结果。

      【讨论】:

      • 应该是什么类型的?当我将打印语句更改为[1;2;3] 时,它给了我Error: This expression has type int list -> int list but an expression was expected of type int list -> unit Type int list is not compatible with type unit
      • 如果你希望你的函数是多态的,你需要返回与输入列表相同类型的东西。事实上,对于这种情况,您几乎可以肯定只返回输入列表本身。如果不查看所有代码,很难确定。
      猜你喜欢
      • 2018-02-08
      • 2022-01-27
      • 2018-09-25
      • 1970-01-01
      • 2021-10-16
      • 2021-11-23
      • 2021-12-21
      • 1970-01-01
      • 2010-12-05
      相关资源
      最近更新 更多