Lab 10

Here’s the code for bind, lift, getstore, and setstore

  ; hook together a computation and a function that produces a computation:
  (define (bind a b) (lambda (store)
                       (type-case Any*Store (a store)
                         [a*s (x newstore) ((b x) newstore)])))
  
  ; "lift" a value to a computation
  (define (lift a) (lambda (store) (a*s a store)))
  
  ; extract the store from the flow
  (define getstore (lambda (store) (a*s store store)))
  
  ; invject a new store into the flow
  (define (setstore newstore) (lambda (dc) (a*s #f newstore)))
  
  ; run a computation.  The top-level wrapper.
  (define (run c) (c (mtSto)))
  
  ; run a computation. Discard the store at the end of
  ; the computation.
  (define (run/trim c) (a*s-val (run c)))
  
  
  ; here's the representation of an Any*Store:
  (define-type Any*Store
    [a*s (val any/c) (store Store?)])
  
  
  ; here's the representation of a store.  Note that we've replaced
  ; MOCFAE-Value with 'number' for the purposes of the lab:
  
    ; represents a store mapping locations to values
  (define-type Store
    [mtSto]
    [aSto (location number?) (value number?) (store Store?)])
  
  ; given a location and a value, store the value in the location.
  ; written using the store monad.
  (define (update-store location val)
    (sdo (s <- getstore)
         (setstore (aSto location val s))))
  
  ; ... and here's the "sdo" macro.
  
  (define-syntax (sdo stx)
    (syntax-case stx (<-)
      ; base cases:
      [(_ (name <- comp)) #'comp]
      [(_ comp) #'comp]
      ; non-base-cases:
      [(_ (name <- comp1) clause ...)
       #`(bind comp1 (lambda (name) (sdo clause ...)))]
      [(_ comp1 clause ...)
       #`(bind comp1 (lambda (bogusname) (sdo clause ...)))]))

Here’s a simple test case:

  (run
   (sdo (update-store 3 4) ; put a '4' in location 3
        (update-store 4 5) ; put a '5' in location 4
        (lift 13)))

Exercises: