reasonML 类型高阶函数

reasonml type higher order function

提问人:hesxenon 提问时间:10/20/2019 最后编辑:glennslhesxenon 更新时间:10/20/2019 访问量:163

问:

给定以下模块,编译器会引发错误

  41 │ };
  42 │ 
  43 │ module TestB = {
  44 │   let minFn = (a, b) => a < b ? a : b;
   . │ ...
  54 │   let max = reduceList(maxFn);
  55 │ };
  56 │ 
  57 │ // module Number = {

  The type of this module contains type variables that cannot be generalized:
  {
    let minFn: ('a, 'a) => 'a;
    let maxFn: ('a, 'a) => 'a;
    let reduceList: ('a, list('b)) => option('b);
    let min: list('_a) => option('_a);
    let max: list('_a) => option('_a);
  }

这似乎是因为我只部分地将参数应用于 。现在,我已经得到了一些关于价值限制的信息,在我看来,这就是这里发生的事情。reduceList

我已经尝试过显式键入函数及其定义位置,并显式键入整个模块,因为我认为这就是您应该根据有关值限制的部分来解决这个问题的方式。然而,这似乎没有区别。minmax

module TestB = {
  let minFn = (a, b) => a < b ? a : b;
  let maxFn = (a, b) => a > b ? a : b;
  let reduceList = (comp, numbers) =>
    switch (numbers) {
    | [] => None
    | [head] => Some(head)
    | [head, ...tail] => Some(List.fold_left(minFn, head, tail))
    };

  let min = reduceList(minFn);
  let max = reduceList(maxFn);
};

另一方面......类型在这里有什么特别的意义吗?_

OCAML 原因 部分应用 值限制

评论


答:

3赞 glennsl 10/20/2019 #1

这确实是因为值限制。我看不出您引用的文档部分是否说明了如何使用类型注释来避免它,尽管在我看来它也应该如此。希望这里有一些有经验的OCamler可以解释为什么它没有。

据我所知,除非类型注释不包含任何类型变量,从而删除多态性,否则它不会,而且我认为这不是您想要的。解决此问题的最简单方法是使用 eta 扩展,即使参数显式化,而不是使用部分应用程序。这同时演示了以下两个方面:

module TestB = {
  let minFn = (a, b) => a < b ? a : b;
  let maxFn = (a, b) => a > b ? a : b;
  let reduceList = (comp, numbers) =>
    switch (numbers) {
    | [] => None
    | [head] => Some(head)
    | [head, ...tail] => Some(List.fold_left(minFn, head, tail))
    };

  let min = x => reduceList(minFn, x);
  let max : list(int) => option(int) = reduceList(maxFn);
};

下划线 in 表示它是一个弱类型变量,如您引用的文档中所述:_'_a

名称以_weak前缀(如“_weak1)开头的类型变量是弱多态类型变量,有时缩写为弱类型变量。弱类型变量是当前未知的单个类型的占位符。一旦知道占位符类型“_weak1后面的特定类型 t,所有出现的 '_weak1 都将替换为 t。

评论

1赞 octachron 10/20/2019
你是对的,不可能(在 OCaml 中)使用类型注释删除弱多态类型变量。
0赞 hesxenon 10/20/2019
需要明确的是,ETA 扩展是 并且只是删除多态性对吗?x => reduceList(minFn, x);let max: list(int) => option(int) = reduceList(maxFn);
0赞 glennsl 10/20/2019
@DanielPotensky正确!