(* Lecture 16: Mutation and State *) (* Author: Frank Pfenning *) (* Polymorphism revisited *) let (* val head : 'a * 'a list -> 'a *) fun head (_, x::l) = x | head (default, nil) = default in (head (3, 4::nil), head (true, nil)) end; (* val it : (int * bool) = (4, true) *) (* following is a type error *) (* fun error (head) = (head (3, 4::nil), head (true, nil)); *) (* :1,39 to 1,54: error: Function applied to argument of wrong type Near: head (true, nil) Required argument type: (int * int list) Actual argument type: (bool * 'a list) Type clash between int and bool *) let (* val id : 'a -> 'a *) val id = fn x => x in id id 3 (* (id : (int -> int) -> (int -> int)) (id : int -> int) 3 : int *) end; (* val it : int = 3 *) (* Another type error below *) (* fun error id = id id 3; *) (* :1,16 to 1,20: error: Circularity in function application Near: id id Required argument type: 'a Actual argument type: 'a -> 'b Circular type results from unifying 'a and 'a -> 'b *) (* Polymorphic references *) (* Below must give type error *) (* let val r = ref (fn x => x) (* r : ('a -> 'a) ref *) in ( r := (fn x => x + 1) ; (* r : (int -> int) ref *) (!r) true ) (* r : (bool -> bool) ref *) end; *) (* Consequences of value restriction *) (* for pure programs *) let val x = nil in (true::x,1::x) end; (* Type errors below *) (* let val y = rev nil in (true::y,1::y) end; val y = ref nil; *) (* A note on equality types *) (* 'a ref is always an equality type, independently of 'a *) (* it compares cells, not their contents *) (* Similarly for arrays *) (***********************) (* Encapsulating State *) (***********************) (* signature GAME = sig datatype player = Player | Opponent type move ... structure DisplayBoard : sig exception IllegalMove type match (* encapsulates current state *) val init : unit -> match (* initialize starting position *) val quit : match -> unit (* finish match *) val applyMove : match -> player -> move -> unit (* apply a move *) (* raises IllegalMove *) val showBoard : match -> unit (* show the current position *) datatype action = Move of move | Quit val showAction : match -> action -> unit (* show a move or "quit" *) val readAction : match -> unit -> action (* read a move or "quit" *) end end; *)