OCaml 中的 eta 扩展是否万无一失?

Is eta-expansion foolproof in OCaml?

在 OCaml 中最好始终将 eta-expand 作为万无一失的经验法则吗?


  type 'x recordx = { x : int }
  type 'y recordy = { y : int }

  let rec ok : type n a. n recordx -> a recordy -> int =
   fun algebrah x -> ok algebrah x

  let rec ok : type a. a recordy -> int =
   fun x ->
    let go : type b. b recordy -> int = ok in
    go x

  let rec ok : type n a. n recordx -> a recordy -> int =
   fun x y ->
    let go : type b. b recordy -> int = fun y -> ok x y in
    go y

  let rec ok : type n a. n recordx -> a recordy -> int =
   fun x y ->
    let go = ok x in
    go y

  (* This definition has type 
          'b recordy -> int which is less general than
    'b0. 'b0 recordy -> int 
  *)
  let rec ko : type n a. n recordx -> a recordy -> int =
   fun x y ->
    let go : type b. b recordy -> int = ko x in
    go y

放宽的值限制将 eta 扩展形式 fun y -> f x y 分类为可以通过 let 绑定泛化的值,与非值 f y 相反。参见 https://ocaml.org/manual/polymorphism.html#s%3Aweak-polymorphism

此外,在像 OCaml 这样的急切语言中,eta 扩展确实改变了函数的语义。考虑

let print x =
  Format.printf "x=%s@." x;
  fun y -> Format.printf "y=%s@."

let print1 = print "x"
let print2 y = print "x" y

因此,eta-expansion 是一种语义变化转换,而不是“万无一失”的转换。