Reputation: 1
datatype 'a instr = Put of 'a|Get|Restore;
fun makeCell (n:int):('a instr->unit)=
let val stack = ref [] in
(fn (instruction:'a instr)=>
case instruction of
Put (x) => ((stack := x :: !stack))
|Get => stack := []
|Restore => (stack := []))
end;
val alice = makeCell 0;
alice (Put (3));
alice (Put 3);
alice (Get);
alice (Get);
it returns an error when i build:
val alice = fn : ?.X1 instr -> unit
/usr/local/smlnj/bin/sml: Fatal error -- Uncaught exception Error with 0
raised at ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
/Users/Carl/Desktop/assignment 4.sml:113.1-113.16 Error: operator and operand don't agree [literal]
operator domain: ?.X1 instr
operand: int instr
in expression:
alice (Put 3)
What Should I do to fix this problem? I have tried different approaches, but none of them have worked.
Upvotes: 0
Views: 300
Reputation: 66823
Types like ?.X1
are created when the value restriction is violated.
Your definition of alice
creates a violation because it defines alice
as something other than a value. (Your definition is a function application). Hence your alice
can't be fully polymorphic.
Here's a definition that is closer:
fun alice x = (makeCell 0) x
This modification of the definition is called eta expansion.
Unfortunately, this definition makes a new cell for each call. (Your current definitions don't allow this to be observed, however.)
Here's a definition that works for your test code and uses a single cell:
val alice : int instr -> unit = makeCell 0
It doesn't make sense for alice
to be fully polymorphic while using just a single ref cell. A single cell can contain values of only one type.
Upvotes: 3