aboutsummaryrefslogtreecommitdiff
path: root/examples/state-minimal.scm
blob: 8a88ac6afeb4132cb2ac938d248616a8527a9cc5 (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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
(use-modules (ice-9 curried-definitions)
             (ice-9 match))

;;; This is a minimal implementation of the state monad.
;;; It is incompatible with the rest of my monad system,
;;; since everything either has type <pair> or <procedure>.
;;; But it should work as a nice base for the actual
;;; implementation.

;;; This implementation works, as far as I can tell, exactly
;;; like the Haskell version (of MonadState). But obviously
;;; without all the nice syntax.

;;; Anything that takes an st-list and returns an st-list is
;;; considered a State value.
;;; An st-list is a list where the car is the last returned
;;; value, and the cadr is the "state".

;; newtype State = st-list -> st-list

;; State
(define ((get) st-list)
  "Sets the return value to the state value"
  (match st-list
    ((v st)
     (list st st))))

;; v -> State
(define ((put v) st-list)
  "Sets the state value to v, sets the return value to ()"
  (list '() v))

;; State -> (v -> State) -> State
(define ((bind st-proc proc) st-list)
  (let ((new-st-list (st-proc st-list)))
    (match new-st-list
      ((v _)
       ((proc v) new-st-list)))))

;; State -> State -> State
(define ((then st-proc-1 st-proc-b) st-list-a)
  (let ((st-list-b (st-proc-1 st-list-a)))
    (st-proc-b st-list-b)))

;; v -> State
(define ((return v) st-list)
  "Sets the return value to v"
  (cons v (cdr st-list)))

;; State -> v -> (r v)
(define (run-state st-proc init)
  "Exec state with init as starting state value"
  (st-proc (list init init)))