我正在尝试定义新类型的数据,创建列表,然后从列表中创建流:
type 'a myType = Name of char ;;
let myList = [Name('a')];;
let myStream = Stream.of_list myList;;
错误:此表达式的类型'_a myType Stream.t, 包含无法推广的类型变量
有什么想法吗?
答案 0 :(得分:5)
在您的代码中,myStream
是由未知类型(在上面的错误中称为myType
)参数化的'_a
类型的流。编译器在代码中没有找到关于'_a
应该是什么的足够信息。
在某些情况下,编译器会通过声明'_a
可以是任何内容来推广该类型。例如,myList
已正确标识为'a myType list
。但是,假设Stream.t
是抽象类型,泛化可能会导致错误,因此不会执行。
解决此问题的一种方法是指定'_a
的类型,如果您只打算将其用于单一类型,例如使用类型约束:
let myStream : int myType Stream.t = ...
另一种方式,如果你想保持它的通用性,就把它变成一个函数(然后自动推广):
let myStream () = Stream.of_list myList
预期类型为unit -> 'a myType Stream.t
。
这种泛化可能导致错误的根本原因是存在可变状态。假设我定义了四个文件:
(* ref.ml *)
let x = ref None
(* ref.mli *)
val x : 'a option ref
(* a.ml : 'a = string *)
Ref.x := Some "Hello"
(* b.ml : 'a = int *)
match !ref x with None -> () | Some i -> print_int i
这会导致运行时错误。因此,只要涉及可变状态,就不能推广类型。