签名不匹配'列表 - > ' Core.Std.List.t未包含在'列表中 - > ' a t

时间:2015-04-13 04:29:32

标签: ocaml ocaml-core

我正在编写“More Ocaml”一书的第11章,您尝试以各种方式实现集合。这段代码很大程度上来自本书,但我已将其更改为使用Core(和Core的List)而不是stdlib。

open Core.Std;;
open Printf;;

module SetList :
  sig
    type 'a t;;
    val set_of_list : 'a list -> 'a t;;
    val list_of_set : 'a t -> 'a list;;
    val insert : 'a -> 'a t -> 'a t;;
    val size : 'a t -> int;;
    val member : 'a t -> 'a -> bool;;
  end
=
  struct
    type 'a t = 'a list;;

    let member = List.mem ~equal:(=);;

    let insert x l = if member l x then l else x::l;;

    let rec set_of_list l = match l with
      [] -> []
      |h::t -> insert h (set_of_list t);;

    let list_of_set x = x;;

    let size = List.length;;
  end;;

这给了我一个错误Values do not match: val set_of_list : '_a list -> '_a Core.Std.List.t is not included in val set_of_list : 'a list -> 'a t

第一个问题,我该怎么做才能解决这个错误?第二个也是更重要的,为什么编译器不会意识到'a Core.Std.List.t等于'a t并且匹配第15行给定定义的值。

2 个答案:

答案 0 :(得分:2)

你错了。如果我们给出选项-short-path(它在给出类型错误时试图找到最小的类型别名),我们会得到以下错误:

   Values do not match:
     val set_of_list : '_a t -> '_a t
   is not included in
     val set_of_list : 'a t -> 'a t

所以Core.Std.List.t确实等于t,编译器会看到它。问题在于偷偷摸摸的_

错误的原因是所谓的价值限制。基本上,只有在绑定值时,类型检查器才能推广(选择最常规的类型)。在您的情况下,剔除是member的定义。

如果你这样定义,错误就会消失:

let member x = List.mem ~equal:(=) x

列表绑定到一个名称,因此类型检查器可以概括。

当编译器无法生成时,它会生成一个类型变量,该变量是"未知但不是多态的" (我们将它们称为单态)并将_添加到名称中。类型变量将在首次使用时专用。您可以尝试在顶层中使用let r = ref None来更仔细地查看它。

答案 1 :(得分:1)

你遇到了价值限制,需要eta扩展你的功能,例如,

let member lst = List. ~equal:(=) lst

关于价值限制,即SO中的弱类型多态性,有很多问题和答案,所以我认为快速搜索会揭示更多信息。

'a Core.Std.List.t'a list的类型同义词,因此不存在任何问题。应该为你敲钟的部分是'_a类型中的这个激烈的下划线。这被称为弱类型变量。