Create a gist now

Instantly share code, notes, and snippets.

@RayRacine /try.rkt Secret
Created Mar 16, 2012

#lang typed/racket/base
(provide
(struct-out Failure)
(struct-out Success)
failed succeded get invert
try-map try-flatmap try-foreach try-filter try-exists
rescue recover
try continue with-try)
(struct: (T) Failure ([exception : exn]))
(struct: (T) Success ([result : T]))
(define-type (Try T) (U (Failure T) (Success T)))
(: failed (All (T) (Try T) -> Boolean))
(define (failed try)
(Failure? try))
(: succeded (All (T) (Try T) -> Boolean))
(define (succeded try)
(Success? try))
(: get (All (T) (Try T) -> T))
(define (get try)
(cond
((Failure? try) (raise (Failure-exception try)))
((Success? try) (Success-result try))))
;; Is a generic "lens" library on structures possible??
;; Higher kinded types, L is a type constructor binding for M (Success) and N (Failure)
;; (: S-map (All (L T U) (L T) (T -> U) -> (L U)))
(: try-map (All (T U) (Try T) (T -> U) -> (Try U)))
(define (try-map try fn)
(cond
((Success? try)
(Success (fn (Success-result try))))
((Failure? try) try)))
(: try-flatmap (All (T U) (Try T) (T -> (Try U)) -> (Try U)))
(define (try-flatmap try fn)
(cond
((Success? try)
(with-handlers ([exn:fail? (λ: ((ex : exn))
(Failure ex))])
(fn (Success-result try))))
((Failure? try) try)))
(: try-foreach (All (T U) (Try T) (T -> U) -> Void))
(define (try-foreach try fn)
(cond
((Success? try)
(fn (Success-result try))
(void))
((Failure? try)
(void))))
(: try-filter (All (T) (Try T) (T -> Boolean) -> (Try T)))
(define (try-filter try select?)
(cond
((Success? try) ;; need to see of Racket has strutural pattern matching kindof cond!!!
(if (select? (Success-result try))
try
(Failure (exn:fail (format "Unsatisfied try filter predicate for ~s" (Success-result try))
(current-continuation-marks)))))
((Failure? try)
try)))
(: try-exists (All (T) (Try T) (T -> Boolean) -> Boolean))
(define (try-exists try exists?)
(cond
((Success? try)
(exists? (Success-result try)))
((Failure? try) #f)))
(: invert ((Try exn) -> (Try exn)))
(define (invert try)
(cond
((Success? try)
(Failure (exn:fail (format "Inverted try. Success for ~s is Failure" (Success-result try))
(current-continuation-marks))))
((Failure? try)
(Success (Failure-exception try)))))
(: continue (All (T V W) (Try T) (T -> (Try V)) (exn -> (Try W)) -> (Try (U V W))))
(define (continue try on-success on-failure)
(cond
((Success? try)
(on-success (Success-result try)))
((Failure? try)
(on-failure (Failure-exception try)))))
;; Rescue a failed computation if the rescue function is capable of doing so.
;; Careful of side effects by the rescue function.
;; Should my-hero be a PartialFunction as opposed to one which returns Option.
(: rescue (All (T) (Try T) ((Failure T) -> (Option (Try T))) -> (Try T)))
(define (rescue try my-hero)
(with-handlers ([exn:fail? (λ (ex)
(Failure ex))])
(cond
((Failure? try)
(let ((result (my-hero try)))
(if result
result
try)))
((Success? try) try))))
(: recover (All (T) (Try T) ((Failure T) -> (Option T)) -> (Try T)))
(define (recover try my-heroine)
(with-handlers ([exn:fail? (λ (ex)
(Failure ex))])
(cond
((Failure? try)
(let ((result (my-heroine try)))
(if result
(Success result)
try)))
((Success? try) try))))
(: try (All (T) (-> T) -> (Try T)))
(define (try thunk)
(with-handlers ([exn:fail? (lambda (ex)
(Failure ex))])
(Success (thunk))))
(define-syntax with-try
(syntax-rules ()
((_ body ...)
(try (lambda () body ...)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment