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.