【问题标题】:type inference in OCaml says my function is 'a list list -> list while it should be 'a listOCaml 中的类型推断说我的函数是 'a list list -> list 而它应该是 'a list
【发布时间】:2022-01-05 16:55:33
【问题描述】:

我是 OCaml 的新手,对函数式编程的经验很少。 我写了以下函数

let rec reverse l =
  match l with
  | [] -> []
  | h::rest -> (reverse rest) @ h

它应该反转列表中的元素,例如将[1;2;3] 转换为[3;2;1]。 我不知道该函数是否可以工作,但问题是 OCaml 推断该函数为 'a list list -> 'a list 类型,而我希望它是 'a list -> 'a list

# reverse [1;2;3;4];;
Error: This expression has type int but an expression was expected of type 'a list

【问题讨论】:

    标签: functional-programming ocaml type-inference


    【解决方案1】:

    连接运算符@ 期望它的两个操作数都是列表。

    当你写(reverse rest) @ h时,立即推断h一定是一个列表。由于l = h::resth 是一个列表,那么l 必须是一个列表的列表。

    请尝试将(reverse rest) @ h 替换为(reverse rest) @ [h]。这应该可以正常工作。

    但是,请注意串联a @ b 的时间与a 的长度呈线性关系。由于您反复调用此连接,因此算法的整体复杂性是二次的。那很慢。如果您使用累加器逐步构建反转列表,实际上可以在线性时间内反转列表,只使用:: 而从不使用@

    【讨论】:

    • 谢谢!现在我并不真正关心性能,因为我只是在学习一种全新的编程方式,但我感谢你的帮助。以后一定会尝试制作线性时间版本!
    【解决方案2】:

    OCaml 类型检查器始终为实现推断最佳类型((除了 GADT、高级多态性和一流模块等高级功能之外))。

    因此,如果推断的函数类型与您的预期不符,则表示您的实现存在错误。

    这里的问题是(@) 的类型是'a list -> 'a list -> 'a list。因此reverse rest @ h 暗示:

    • h 是一个列表(因此 l 是某个元素 'b 的列表的列表)。
    • reverse resth 相同类型

    因此,reverse 的类型为'b list list -> 'b list

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-18
      • 1970-01-01
      • 2018-04-30
      • 2021-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-23
      相关资源
      最近更新 更多