blob: 7036cb96d1aafb875975ed1a88dd7b9b247d8f41 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
;;; Commentary:
;; The writer monad creates a context where strings are automatically collected.
;; This is useful both for logging and output construction.
;;
;; The writer monad uses the state monad internally, but it's considered a leak
;; in the abstraction to access it directly (even though there is nothing
;; stoping you).
;;; Code:
(define-module (monad writer)
#:use-module (monad)
#:use-module (monad state)
#:use-module (oop goops)
#:re-export (>>)
#:export (w return-writer
run-writer
with-writer))
(define (w str)
"writes str to the current writer monad"
(modify (lambda (st) (string-append st str))))
(define return-writer return-state)
(define (run-writer w)
"Wrapper around run-state, but inserts an empty string as starting state."
(run-state w ""))
(define-method (>> (s <string>) other)
"A bit of a hack, but this allows strings to be placed directly inside a
@code{do} block, and have them written to the current writer context."
(>> (w s) other))
(define (with-writer proc . values)
"Runs a regular procedure on values, but also logs the call"
(do let return = (apply proc values)
(format #f "Applied ~s to ~s ⇒ ~s\n"
(procedure-name proc)
values return)
(return-writer return)))
|