Stream.of_list with custom data types
I am trying to define a new type of data, to create a list and then to create a stream out of the list:
type 'a myType = Name of char ;;
let myList = [Name('a')];;
let myStream = Stre开发者_开发百科am.of_list myList;;
Error: The type of this expression, '_a myType Stream.t, contains type variables that cannot be generalized
Any idea?
In your code, myStream
is a stream of type myType
parametrized by an unknown type (which is called '_a
in your error above). The compiler did not find enough information in your code about what '_a
should be.
In some cases, the compiler would then generalize the type by stating that '_a
can be anything. For instance, myList
is properly identified as 'a myType list
. However, given that Stream.t
is an abstract type, generalization might cause errors, so it is not performed.
One way to work around this is to specify the type of '_a
if you only intend it to be used with a single type, for instance with a type constraint :
let myStream : int myType Stream.t = ...
Another way, if you wish to keep it generic, is to turn it into a function (which is then automatically generalized) :
let myStream () = Stream.of_list myList
The type will be unit -> 'a myType Stream.t
as expected.
The underlying reason why such generalization might cause errors is the presence of mutable state. Suppose that I define four files as such:
(* 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
This would cause a runtime error. As such, whenever mutable state is involved, types cannot be generalized.
精彩评论