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:
Develop the ’addfour’ function, that adds 4 to a number. It must be written in a monadic style, so that this test case succeeds:
(test (run/trim (addfour 13)) 17)
Develop the ’store-lookup/helper’ function, that accepts a Store and a location and returns the value in that location. This function should not be monadic; write this function the same way you would have in weeks gone by.
Develop the ’store-lookup’ function, that is written in monadic style and satisfies this test case:
(test (run/trim (sdo (update-store 14 2398) (store-lookup 14))) 2398) It should use the store-lookup/helper function.
Develop the double/ctr monadic function, that doubles its input and also increases the number stored in location 23 by one.
Develop the monadic doMap method, that accepts a monadic function and a list and returns the result of mapping the function across the arguments.
Here’s a test case, using the double/ctr function that you defined earlier.
(test (run/trim (sdo (update-store 23 0) [l <- (doMap double/ctr (list 3 4 5))] [n <- (store-lookup 23)] (return (list l n)))) (list (list 6 8 10) 3)) Show me this function when you’re done, for lab credit.