我正在尝试定义一种新类型的数据,创建一个列表,然后从列表中创建一个流:
type 'a myType = Name of char ;;
let myList = [Name('a')];;
let myStream = Stream.of_list myList;;
Run Code Online (Sandbox Code Playgroud)
错误:此表达式的类型'_a myType Stream.t包含无法一般化的类型变量
任何的想法?
在您的代码中,myStream是一个myType由未知类型参数化的类型的流('_a在上面的错误中调用).编译器在代码中没有找到足够的信息'_a.
在某些情况下,编译器会通过声明'_a可以是任何内容来概括类型.例如,myList被正确识别为'a myType list.但是,如果这Stream.t是一个抽象类型,泛化可能会导致错误,因此不会执行.
解决此问题的一种方法是指定类型,'_a如果您只打算将其用于单个类型,例如使用类型约束:
let myStream : int myType Stream.t = ...
Run Code Online (Sandbox Code Playgroud)
另一种方法,如果你想保持它的通用性,就是把它变成一个函数(然后自动推广):
let myStream () = Stream.of_list myList
Run Code Online (Sandbox Code Playgroud)
类型将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
Run Code Online (Sandbox Code Playgroud)
这会导致运行时错误.因此,只要涉及可变状态,就不能推广类型.