Created
June 5, 2018 02:36
-
-
Save jeandrek/3b15a47c364ef5b19c8f145c07f31f31 to your computer and use it in GitHub Desktop.
Haskell I/O monad in Scheme
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;;;; Monads | |
(define (return x) (make-result x)) | |
(define (bind m k) | |
(make-thunk (lambda () (execute! (k (execute! m)))))) | |
(define (execute! m) | |
(cond ((result? m) (result-value m)) | |
((thunk? m) (execute-thunk! m)))) | |
;;;; Haskell 'do' syntax | |
(define-syntax io-begin | |
(syntax-rules (let) | |
((io-begin exp) exp) | |
((io-begin (let var exp) exps ...) | |
(bind exp (lambda (var) (io-begin exps ...)))) | |
((io-begin exp exps ...) | |
(bind exp (lambda (x) (io-begin exps ...)))))) | |
(define (io-monad? obj) | |
(or (result? obj) (action? obj))) | |
;;;; Data representation | |
(define (make-result x) (cons 'result x)) | |
(define (make-thunk p) (cons 'thunk p)) | |
(define (result? obj) (tagged-list? obj 'result)) | |
(define (thunk? obj) (tagged-list? obj 'thunk)) | |
(define (result-value m) (cdr m)) | |
(define (execute-thunk! m) ((cdr m))) | |
(define (tagged-list? obj tag) | |
(and (pair? obj) | |
(eq? (car obj) tag))) | |
;;;; I/O operations | |
(define (io-write obj) | |
(make-thunk (lambda () (write obj)))) | |
(define (io-write-char char) | |
(make-thunk (lambda () (write-char obj)))) | |
(define (io-display str) | |
(make-thunk (lambda () (display str)))) | |
(define io-read (make-thunk read)) | |
(define io-read-char (make-thunk read-char)) | |
;; (define (read-line) | |
;; (let loop ((accum '())) | |
;; (let ((char (read-char))) | |
;; (if (or (eof-object? char) (char=? char #\newline)) | |
;; (list->string (reverse accum)) | |
;; (loop (cons char accum)))))) | |
;; (define io-read-line (make-thunk read-line)) | |
(define io-read-line | |
(let loop ((accum '())) | |
(io-begin | |
(let char io-read-char) | |
(if (or (eof-object? char) (char=? char #\newline)) | |
(return (list->string (reverse accum))) | |
(loop (cons char accum)))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment