Changeset 26985 in project
 Timestamp:
 07/05/12 04:47:03 (9 years ago)
 File:

 1 edited
Legend:
 Unmodified
 Added
 Removed

wiki/eggref/4/monad
r26566 r26985 41 41 Yes, sometimes this isn't strictly a necessary set of functionality. But for when it is, save yourself some time and write a monad. 42 42 43 === What's this about lazy evaluation?44 45 Yes, this monad implementation is lazily evaluated.46 47 48 43 === Functions 49 44 50 ==== (definemonad name unitfunction bindfunction )45 ==== (definemonad name unitfunction bindfunction [failfunction]) 51 46 52 47 <procedure>(definemonad name unitfunction bindfunction [failfunction])</procedure> … … 73 68 <tr><td>>>=</td><td>Maps to bind</td></tr> 74 69 <tr><td>return</td><td>Maps to unit</td></tr> 70 <tr><td>fail</td><td>Maps to fail</td></tr> 75 71 </table> 76 72 … … 133 129 Similar to the (using) procedure, but allows for even more terseness. 134 130 135 Within the (dousing) body a special binding syntax is allowed, which can be understood by this example: 131 Within dousing the following will be defined: 132 133 <table> 134 <tr><th>Function</th><th>Usage</th></tr> 135 <tr><td>>>=</td><td>Maps to bind</td></tr> 136 <tr><td>return</td><td>Maps to unit</td></tr> 137 <tr><td>fail</td><td>Maps to fail</td></tr> 138 <tr><td>/m</td><td>Shorthand for calling monadspecific functions, details follow</td></tr> 139 <tr><td>/m!</td><td>Shorthand for calling monadspecific functions, details follow</td></tr> 140 <tr><td><</td><td>Shorthand for binding a symbol to a monadic value, details follow</td></tr> 141 </table> 142 143 ===== /m! Keyword 144 145 The /m! keyword is used as a shortcut for referencing monadspecific procedures which are prefixed with the current monad name. 146 147 For example: 148 149 <enscript highlight="scheme"> 150 (dousing <writer> (/m! tell 1)) 151 </enscript> 152 153 Is the same as: 154 155 <enscript highlight="scheme"> 156 (dousing <writer> (<writer>tell 1)) 157 </enscript> 158 159 ===== /m Keyword 160 161 The /m keyword is like /m!, except that it references the procedure without executing it. 162 163 For example: 164 165 <enscript highlight="scheme"> 166 (dousing <state> (x < (/m get)) (return x)) 167 </enscript> 168 169 Is the same as: 170 171 <enscript highlight="scheme"> 172 (dousing <writer> (x < <state>get) (return x)) 173 </enscript> 174 175 ===== < Keyword 176 177 The < keyword is used as a shortcut for binding a value within a monad. 178 179 For example: 180 181 <enscript highlight="scheme"> 182 (dousing <maybe> 183 (x < (return 1)) 184 x) 185 </enscript> 186 187 Is the same as: 188 189 <enscript highlight="scheme"> 190 (dousing <maybe> 191 (>>= (return 1) 192 (lambda (x) 193 (dousing <maybe> 194 x)))) 195 </enscript> 196 197 ===== General Example 198 199 A simple example: 136 200 137 201 <enscript highlight="scheme"> … … 139 203 (x < (return <maybe> 1)) 140 204 x) 141 205 142 206 ;Returns: 143 207 (Just 1) … … 148 212 <enscript highlight="scheme"> 149 213 (dousing <maybe> 150 (x < (return <maybe>1))214 (x < (return 1)) 151 215 (if (eq? 2 (cadr x)) 152 (return <maybe>'Banana)153 (fail <maybe>))154 (y < (return <maybe>'Apple))216 (return 'Banana) 217 (fail)) 218 (y < (return 'Apple)) 155 219 y) 220 156 221 ;Returns: 157 222 Nothing 158 223 </enscript> 159 224 225 ==== (do monad [body ...]) 226 227 <procedure>(do monad [body ...])</procedure> 228 229 Alias for (dousing monad [body ...]). 230 160 231 === Basic Monads 161 232 … … 165 236 166 237 <enscript highlight="scheme"> 167 168 169 170 238 (definemonad 239 <id> 240 (lambda (a) a) 241 (lambda (a f) (f a))) 171 242 </enscript> 172 243 … … 174 245 175 246 <enscript highlight="scheme"> 176 (definemonad 177 <maybe> 178 (lambda (a) a) 179 (lambda (a f) (if a (f a) #f)) 180 (caselambda (() 'Nothing) 181 ((_ . _) 'Nothing))) 247 (definemonad 248 <maybe> 249 (lambda (a) a) 250 (lambda (a f) (if a (f a) #f)) 251 (caselambda (() 'Nothing) 252 ((_ . _) 'Nothing))) 253 </enscript> 254 255 ===== Example 256 257 <enscript highlight="scheme"> 258 > (do <maybe> 259 (if #t 260 'Nothing 261 '(Just First)) 262 '(Just Second)) 263 Nothing 182 264 </enscript> 183 265 … … 185 267 186 268 <enscript highlight="scheme"> 187 (definemonad 188 <list> 189 (lambda (a) (list a)) 190 (lambda (a f) (concatenate! (map! f a)))) 269 (definemonad 270 <list> 271 (lambda (a) (list a)) 272 (lambda (a f) (concatenate! (map! f a)))) 273 </enscript> 274 275 ===== Example 276 277 <enscript highlight="scheme"> 278 #;> (do <list> 279 (x < '(1 2 3)) 280 (y < '(a b c)) 281 (return `(,x ,y))) 282 ((1 a) (1 b) (1 c) (2 a) (2 b) (2 c) (3 a) (3 b) (3 c)) 191 283 </enscript> 192 284 … … 194 286 195 287 <enscript highlight="scheme"> 196 (definemonad 197 <state> 198 (lambda (a) (lambda (s) `(,a . ,s))) 199 (lambda (a f) 200 (lambda (s) 201 (let* ((p (a s)) 202 (a^ (car p)) 203 (s^ (cdr p))) 204 ((f a^) s^))))) 288 (definemonad 289 <state> 290 (lambda (a) (lambda (s) `(,a . ,s))) 291 (lambda (a f) 292 (lambda (s) 293 (let* ((p (a s)) 294 (a^ (car p)) 295 (s^ (cdr p))) 296 ((f a^) s^))))) 297 </enscript> 298 299 ===== Extra Methods 300 301 ====== <state>get 302 303 <procedure>(<state>get s)</procedure> 304 305 Retrieves the current state from a given <state> monad. 306 307 ======= Example 308 309 <enscript highlight="scheme"> 310 #;> ((do <state> 311 (x < (/m get)) 312 (return x)) 313 "Hi!") 314 ("Hi!" . "Hi!") 315 </enscript> 316 317 ====== <state>gets 318 319 <procedure>(<state>gets f)</procedure> 320 321 Creates a monad that retrieves a given state after filtering it with the function provided. 322 323 ======= Example 324 325 <enscript highlight="scheme"> 326 #;> ((do <state> 327 (x < (/m! gets (lambda (s) (+ s 1)))) 328 (return x)) 329 1) 330 (2 . 1) 331 </enscript> 332 333 ====== <state>modify 334 335 <procedure>(<state>modify f)</procedure> 336 337 Creates a monad that modifies the current state with a given function. 338 339 ======= Example 340 341 <enscript highlight="scheme"> 342 #;> ((do <state> 343 (/m! modify (lambda (v) 344 (display (format "Received: ~S\n" v)) 345 (+ v 1)))) 346 1) 347 Received: 1 348 (() . 2) 349 </enscript> 350 351 ====== <state>put 352 353 <procedure>(<state>put v)</procedure> 354 355 Creates a monad that forces a value into the current <state> monad. 356 357 ======= Example 358 359 <enscript highlight="scheme"> 360 #;> ((do <state> 361 (/m! put 1)) 362 2) 363 (() . 1) 205 364 </enscript> 206 365 … … 208 367 209 368 <enscript highlight="scheme"> 210 (definemonad 211 <reader> 212 (lambda (a) (lambda (v) a)) 213 (lambda (a f) (lambda (v) ((f (a v)) v)))) 369 (definemonad 370 <reader> 371 (lambda (a) (lambda (v) a)) 372 (lambda (a f) (lambda (v) ((f (a v)) v)))) 373 </enscript> 374 375 ===== Extra Methods 376 377 ====== <reader>ask 378 379 <procedure>(<reader>ask m)</procedure> 380 381 Extracts the current value from the current reader monad. 382 383 ======= Example 384 385 <enscript highlight="scheme"> 386 #;> ((do <reader> 387 (x < (/m ask)) 388 (return (+ x 1))) 389 1) 390 2 391 </enscript> 392 393 ====== <reader>asks 394 395 <procedure>(<reader>asks f)</procedure> 396 397 Creates a monad that filters the current value in the reader monad with the given function. 398 399 ======= Example 400 401 <enscript highlight="scheme"> 402 #;> ((do <reader> 403 (/m! asks (lambda (v) 404 (+ v 1)))) 405 1) 406 2 407 </enscript> 408 409 ====== <reader>local 410 411 <procedure>(<reader>local f m)</procedure> 412 413 Creats a monad that first filters the current reader monad value with the provided function, then passes that filtered value to the provided reader monad. 414 415 ======= Example 416 417 <enscript highlight="scheme"> 418 #;> ((do <reader> 419 (/m! local 420 (lambda (v) (+ v 1)) 421 (do <reader> 422 (x < (/m ask)) 423 (return x)))) 424 1) 425 2 214 426 </enscript> 215 427 … … 217 429 218 430 <enscript highlight="scheme"> 219 (definemonad 220 <cps> 221 (lambda (a) (lambda (k) (k a))) 222 (lambda (a f) (lambda (k) (a (lambda (a^) (let ((b (f a^))) (b k))))))) 223 </enscript> 431 (definemonad 432 <cps> 433 (lambda (a) (lambda (k) (k a))) 434 (lambda (a f) (lambda (k) (a (lambda (a^) (let ((b (f a^))) (b k))))))) 435 </enscript> 436 437 ===== Extra Methods 438 439 ====== <cps>call/cc 440 441 <procedure>(<cps>call/cc f)</procedre> 442 443 Creates a monad that, when given a continuation, passes a monad to the provided function that applies the continuation to its input; then applies the continuation to the output of that function. 224 444 225 445 ==== Exception 226 446 227 447 <enscript highlight="scheme"> 228 (definemonad 229 <exception> 230 (lambda (a) `(success ,a)) 231 (lambda (a f) (if (eq? (car a) 'success) (f (cadr a)) a)) 232 (caselambda (() `(failure)) 233 ((a . b) `(failure ,a . ,b)))) 448 (definemonad 449 <exception> 450 (lambda (a) `(success ,a)) 451 (lambda (a f) (if (eq? (car a) 'success) (f (cadr a)) a)) 452 (caselambda (() `(failure)) 453 ((a . b) `(failure ,a . ,b)))) 454 </enscript> 455 456 ===== Extra Methods 457 458 ====== <exception>throw 459 460 <procedure>(<exceptionthrow e)</procedure> 461 462 Synonym for <exception>fail. 463 464 ======= Example 465 466 <enscript highlight="scheme"> 467 #;> (do <exception> (/m! throw "Error! No more cheerios!")) 468 (failure "Error! No more cheerios!") 469 </enscript> 470 471 ====== <exception>catch 472 473 <procedure>(<exception>catch m f)</procedure> 474 475 Creates a monad that examines an exception monad and passes the value to the provided function if it had failed. 476 477 ======= Example 478 479 <enscript highlight="scheme"> 480 #;> (define somemonad 481 (do <exception> 482 (/m! throw "An error happened! Oh no!"))) 483 #;> (do <exception> 484 (/m! catch somemonad 485 (lambda (m) 486 (display (format "Caught an exception: ~S" 487 (cadr m)))))) 488 Caught an exception: "An error happened! Oh no!" 234 489 </enscript> 235 490 … … 237 492 238 493 <enscript highlight="scheme"> 239 (definemonad 240 <writer> 241 (lambda (a) `(,a . ())) 242 (lambda (a f) 243 (let ((b (f (car a)))) 244 `(,(car b) . ,(append (cdr a) (cdr b)))))) 494 (definemonad 495 <writer> 496 (lambda (a) `(,a . ())) 497 (lambda (a f) 498 (let ((b (f (car a)))) 499 `(,(car b) . ,(append (cdr a) (cdr b)))))) 500 </enscript> 501 502 ===== Extra Methods 503 504 ====== <writer>tell 505 506 <procedure>(<writer>tell v)</procedure> 507 508 Creates a monad where the provided value is wrapped in a <writer>. 509 510 ======= Example 511 512 <enscript highlight="scheme"> 513 #;> (do <writer> (/m! tell '(1 2 3))) 514 (() 1 2 3) 515 </enscript> 516 517 ====== <writer>listen 518 519 <procedure>(<writer>listen a)</procedure> 520 521 Creates a monad where the value has been extracted out of the writer. 522 523 ======= Example 524 525 <enscript highlight="scheme"> 526 #;> (do <writer> 527 (x < (/m! listen 528 (/m! tell '(foo)))) 529 (return x)) 530 ((() foo) foo) 531 </enscript> 532 533 ====== <writer>listens 534 535 <procedure>(<writer>listens f m)</procedure> 536 537 Creates a monad that is the outcome of applying the provided function on the given writer monad. 538 539 ======= Example 540 541 <enscript highlight="scheme"> 542 #;> (do <writer> 543 (x < (return (/m! tell '(1 2 3)))) 544 (/m! listens 545 (lambda (l) (map (lambda (v) (+ v 1)) l)) 546 (return x))) 547 ((() 2 3 4)) 548 </enscript> 549 550 ====== <writer>pass 551 552 <procedure>(<writer>pass m)</procedure> 553 554 Creates a monad that is the outcome of mutating the provided writer monad with a given function. Expects to be provided a monad of the form: ((value . function) . restofwriter) 555 556 Not generally used much except by those that know what they're doing, you're likely after <writer>censor for most cases. 557 558 ======= Example 559 560 <enscript highlight="scheme"> 561 #;> (do <writer> 562 (x < (/m! listen 563 `((() . ,(lambda (l) 564 (map (lambda (v) (+ v 1)) l))) 565 . (1 2 3)))) 566 (/m! pass x)) 567 (() 1 2 3 2 3 4) 568 </enscript> 569 570 ====== <writer>censor 571 572 <procedure>(<writer>censor f m)</procedure> 573 574 Creates a monad resulting from the application of the provided function on the given monad, censoring the values that were in the given monad. 575 576 ======= Example 577 578 <enscript highlight="scheme"> 579 #;> (do <writer> 580 (/m! censor (lambda (l) (map (lambda (v) (+ v 1)) l)) 581 (/m! tell '(1 2 3)))) 582 (() 2 3 4) 245 583 </enscript> 246 584 … … 260 598 === Version History 261 599 600 ; 3.0 : Renamed :! to /m! and : to /m due to : already being used for explicit specialization (oops) 601 ; 2.4 : Added :! keyword, fixed : keyword 602 ; 2.3 : Added fail function for all monads which defaults to assert, but is definied appropriately for the <exception> and <maybe> monads. Added : keyword to using and dousing. Added >>=, return and fail bindings to dousing syntax. 262 603 ; 2.2 : Added failure states for monads 263 604 ; 2.1 : Rewrote API to allow for terser execution and a simpler interface. Removed use of promises completely. Removed dotousing, runchain, and run from the API completely. Added dousing syntax. Maybe monad is now selfdefined for it's value or novalue states.
Note: See TracChangeset
for help on using the changeset viewer.