;;; Commentary: ;; ;; Your classical optional (Maybe) monad. ;; It has the constructors @code{just} and @code{nothing}. ;; ;;; Code: (define-module (monad optional) #:use-module (oop goops) #:use-module (monad) #:export (from-just from-maybe wrap-maybe nothing just nothing? just?) #:re-export (>>= >> return)) (define-class ()) (define-class ()) (define-class () (slot #:init-keyword #:slot #:getter from-just)) (define (nothing) (make )) (define (just obj) (make #:slot obj)) (define (nothing? this) (is-a? this )) (define (just? this) (is-a? this )) ;; Returns default if maybe-val is nothing, otherwise ;; the value embedded in maybe-val (define-method (from-maybe default (_ )) default) (define-method (from-maybe _ (m )) (from-just m)) (define (wrap-maybe proc) "Wraps a function in an optional monad, where #f returns are translated to nothing." (lambda values (let ((v (apply proc values))) (if v (just v) (nothing))))) (define-method (write (this ) port) (format port "#" (from-just this))) (define-method (write (this ) port) (format port "#")) (define-method (>>= (_ ) (f )) (nothing)) (define-method (>>= (j ) (f )) (f (from-just j))) (define-method (return (a )) just) (define (curry arg-count proc . collected) (if (zero? arg-count) (apply proc collected) (lambda (x) (apply curry (1- arg-count) proc x collected)))) (define-method (equal? (a ) (b )) (or (and (nothing? a) (nothing? b)) (from-maybe #f #!curly-infix { {(curry 2 equal?) <$> a} <*> b })))