edits
[lambda.git] / topics / week9_mutable_state.mdwn
index e850236..8ee6f9e 100644 (file)
@@ -85,7 +85,7 @@ A different possibility is the *explicit style* for handling mutation. Here we e
                             (* the return value of doing so is () *)
                             (* other return values could also be reasonable: *)
                             (* such as the old value of ycell, the new value, an arbitrary int, and so on *)
                             (* the return value of doing so is () *)
                             (* other return values could also be reasonable: *)
                             (* such as the old value of ycell, the new value, an arbitrary int, and so on *)
-    x + !ycell;;            (* the !ycell operation "dereferences" the cell---it retrieves the value it contains *)
+    x + !ycell              (* the !ycell operation "dereferences" the cell---it retrieves the value it contains *)
 
 Scheme is similar. There are various sorts of reference cells available in Scheme. The one most like OCaml's `ref` is a `box`. Here's how we'd write the same fragment in Scheme:
 
 
 Scheme is similar. There are various sorts of reference cells available in Scheme. The one most like OCaml's `ref` is a `box`. Here's how we'd write the same fragment in Scheme:
 
@@ -240,15 +240,15 @@ The core idea to referential transparency is that when the same value is supplie
     let plus_y x = x + !ycell in
     let first = plus_y 1 in              (* first is assigned the value 2 *)
     ycell := 2; let second = plus_y 1 in (* second is assigned the value 3 *)
     let plus_y x = x + !ycell in
     let first = plus_y 1 in              (* first is assigned the value 2 *)
     ycell := 2; let second = plus_y 1 in (* second is assigned the value 3 *)
-    first = second;;                     (* not true! *)
+    first = second                       (* not true! *)
 
 Notice that the two invocations of `plus_y 1` yield different results, even though the same value is being supplied as an argument to the same function.
 
 Similarly, functions like these:
 
 
 Notice that the two invocations of `plus_y 1` yield different results, even though the same value is being supplied as an argument to the same function.
 
 Similarly, functions like these:
 
-    let f cell = !cell;;
+    let f cell = !cell
 
 
-    let g cell = cell := !cell + 1; !cell;;
+    let g cell = cell := !cell + 1; !cell
 
 may return different results each time they're invoked, even if they're always supplied one and the same reference cell as argument.
 
 
 may return different results each time they're invoked, even if they're always supplied one and the same reference cell as argument.
 
@@ -334,7 +334,7 @@ Let's consider how to interpet our new syntactic forms `newref`, `getref`, and `
 
     and be able to refer back to that cell later by using the result that we assigned to the variable `ycell`. In our simple implementation, we're letting the store just be an `int list`, and we can let the "keys" be indexes in that list, which are (also) just `int`s. Somehow we should keep track of which variables are assigned `int`s as `int`s and which are assigned `int`s as indexes into the store. So we'll create a special type to wrap the latter:
 
 
     and be able to refer back to that cell later by using the result that we assigned to the variable `ycell`. In our simple implementation, we're letting the store just be an `int list`, and we can let the "keys" be indexes in that list, which are (also) just `int`s. Somehow we should keep track of which variables are assigned `int`s as `int`s and which are assigned `int`s as indexes into the store. So we'll create a special type to wrap the latter:
 
-        type store_index = Index of int;;
+        type store_index = Index of int
 
     Our interpretation function will look something like this:
         
 
     Our interpretation function will look something like this:
         
@@ -436,28 +436,28 @@ With a State monad, we call our book-keeping apparatus a "store" instead of an e
 
 Here's the implementation of the State monad, together with an implementation of the Reader monad for comparison:
 
 
 Here's the implementation of the State monad, together with an implementation of the Reader monad for comparison:
 
-    type env = (identifier * int) list;;
+    type env = (identifier * int) list
     (* alternatively, an env could be implemented as type identifier -> int *)
 
     (* alternatively, an env could be implemented as type identifier -> int *)
 
-    type 'a reader = env -> 'a;;
+    type 'a reader = env -> 'a
     let reader_mid (x : 'a) : 'a reader =
     let reader_mid (x : 'a) : 'a reader =
-        fun e -> x;;
+        fun e -> x
     let reader_mbind (xx : 'a reader) (k : 'a -> 'b reader) : 'b reader =
         fun e -> let x = xx e in
                  let yy = k x in
     let reader_mbind (xx : 'a reader) (k : 'a -> 'b reader) : 'b reader =
         fun e -> let x = xx e in
                  let yy = k x in
-                 yy e;;
+                 yy e
 
 
-    type store = int;;
+    type store = int
     (* very simple store, holds only a single int *)
     (* this corresponds to having only a single mutable variable *)
 
     (* very simple store, holds only a single int *)
     (* this corresponds to having only a single mutable variable *)
 
-    type 'a state = store -> ('a, store);;
+    type 'a state = store -> ('a, store)
     let state_mid (x : 'a) : 'a state =
     let state_mid (x : 'a) : 'a state =
-        fun s -> (x, s);;
+        fun s -> (x, s)
     let state_mbind (xx : 'a state) (k : 'a -> 'b state) : 'b state =
         fun s -> let (x, s') = xx s in
                  let yy = k x in
     let state_mbind (xx : 'a state) (k : 'a -> 'b state) : 'b state =
         fun s -> let (x, s') = xx s in
                  let yy = k x in
-                 yy s';;
+                 yy s'
 
 Notice the similarities (and differences) between the implementation of these two monads.
 
 
 Notice the similarities (and differences) between the implementation of these two monads.
 
@@ -465,8 +465,7 @@ With the Reader monad, we also had some special-purpose operations, beyond its g
 
 With the State monad, we'll also have some special-purpose operations. We'll consider two basic ones here. One will be to retrieve what is the current store. This is like the Reader monad's `asks (lookup "x")`, except in this simple implementation there's only a single location for a value to be looked up from. Here's how we'll do it:
 
 
 With the State monad, we'll also have some special-purpose operations. We'll consider two basic ones here. One will be to retrieve what is the current store. This is like the Reader monad's `asks (lookup "x")`, except in this simple implementation there's only a single location for a value to be looked up from. Here's how we'll do it:
 
-    let state_get : store state =
-            fun s -> (s, s);;
+    let state_get : store state = fun s -> (s, s)
 
 This passes through the current store unaltered, and also returns a copy of the store as its payload. (What exactly corresponds to this is the simpler Reader operation `ask`.) We can use the `state_get` operation like this:
 
 
 This passes through the current store unaltered, and also returns a copy of the store as its payload. (What exactly corresponds to this is the simpler Reader operation `ask`.) We can use the `state_get` operation like this:
 
@@ -479,7 +478,7 @@ As we've mentioned elsewhere, `xx >>= fun _ -> yy` can be abbreviated as `xx >>
 The other operation for the State monad will be to update the existing store to a new one. This operation looks like this:
 
     let state_put (new_store : int) : dummy state =
 The other operation for the State monad will be to update the existing store to a new one. This operation looks like this:
 
     let state_put (new_store : int) : dummy state =
-        fun s -> (dummy, new_store);;
+        fun s -> (dummy, new_store)
 
 If we want to stick this in a `... >>= ...` chain, we'll need to prefix it with `fun _ ->` too, like this:
 
 
 If we want to stick this in a `... >>= ...` chain, we'll need to prefix it with `fun _ ->` too, like this:
 
@@ -504,7 +503,7 @@ State monadic **operations** or Kleisli arrows (type `'a -> 'b state`, what appe
 To get the whole process started, the complex computation so defined will need to be given a starting store. So we'd need to do something like this:
 
     let computation = some_state_monad_value >>= operation >>= operation in
 To get the whole process started, the complex computation so defined will need to be given a starting store. So we'd need to do something like this:
 
     let computation = some_state_monad_value >>= operation >>= operation in
-    computation initial_store;;
+    computation initial_store
 
 
 *    See also our [[State Monad Tutorial]]. LINK TODO
 
 
 *    See also our [[State Monad Tutorial]]. LINK TODO
@@ -538,7 +537,7 @@ Programming languages tend to provide a bunch of mutation-related capabilities a
 
         let ycell = ref 1 in
         let xcell = ref 1 in
 
         let ycell = ref 1 in
         let xcell = ref 1 in
-        ycell := 2; !xcell;;
+        ycell := 2; !xcell
         (* evaluates to 1, not to 2 *)
 
     So we have here the basis for introducing a new kind of equality predicate into our language, which tests not for qualitative indiscernibility but for numerical equality. In OCaml this relation is expressed by the double equals `==`. In Scheme it's spelled `eq?` Computer scientists sometimes call this relation "physical equality". Using this equality predicate, our comparison of `ycell` and `xcell` will be `false`, even if they then happen to contain the same `int`.
         (* evaluates to 1, not to 2 *)
 
     So we have here the basis for introducing a new kind of equality predicate into our language, which tests not for qualitative indiscernibility but for numerical equality. In OCaml this relation is expressed by the double equals `==`. In Scheme it's spelled `eq?` Computer scientists sometimes call this relation "physical equality". Using this equality predicate, our comparison of `ycell` and `xcell` will be `false`, even if they then happen to contain the same `int`.