Advertisement
Guest User

pipes in racket (typed no-check)

a guest
Aug 10th, 2012
30
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scheme 5.11 KB | None | 0 0
  1. #lang typed/racket/no-check
  2.  
  3. (require racket/match)
  4.  
  5. ;; Types ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  6.  
  7. (struct: (I O R) Yield ([out : O] [next : (Pipe I O R)]))
  8. (struct: (I O R) Await ([next/f : (I -> (Pipe I O R))]))
  9. (struct: (I O R) Effect ([thunk : (-> (Pipe I O R))]))
  10. (struct: (R) Done ([result : R]))
  11.  
  12. (define-type (Pipe I O R)
  13.   (U (Done R)
  14.      (Effect I O R)
  15.      (Yield I O R)
  16.      (Await I O R)))
  17. (define-type (Conduit I O)
  18.   (All (R) (Pipe I O R)))
  19. (define-type (Source O)
  20.   (All (I) (Pipe I O Void)))
  21. (define-type (Sink I)
  22.   (All (O) (Pipe I O Void)))
  23.  
  24. ;; Pipe monad ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  25.  
  26. (: return/pipe (All (R) (R -> (All (I O) (Pipe I O R)))))
  27. (define (return/pipe x) (Done x))
  28.  
  29. (: bind/pipe
  30.    (All (I O A R) ((Pipe I O A) (A -> (Pipe I O R)) -> (Pipe I O R))))
  31. (define (bind/pipe m f)
  32.   (define (go x) (bind/pipe x f))
  33.   (match m
  34.     [(Done result) (f result)]
  35.     [(Effect thunk) (Effect (λ () (go (thunk))))]
  36.     [(Yield out next) (Yield out (go next))]
  37.     [(Await next/f) (Await (compose go next/f))]))
  38.  
  39. (define-syntax begin/pipe
  40.   (syntax-rules ()
  41.     [(begin/pipe) done]
  42.     [(begin/pipe p) p]
  43.     [(begin/pipe p1 pn ...)
  44.      (bind/pipe p1 (λ (i) (begin/pipe pn ...)))]))
  45.  
  46. (: forever/pipe (All (I O A) ((Pipe I O A) -> (All (R) (Pipe I O R)))))
  47. (define (forever/pipe m)
  48.   (begin/pipe
  49.     m
  50.     (forever/pipe m)))
  51.  
  52. ;; Pipe monad transformer ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  53.  
  54. (define-syntax-rule (lift/pipe e)
  55.   (Effect (λ ()
  56.             (define r e)
  57.             (return/pipe r))))
  58.  
  59. (: lift./pipe (All (A R) ((A -> R) -> (A -> (All (I O) (Pipe I O R))))))
  60. (define (lift./pipe proc)
  61.   (λ (x)
  62.     (Effect (λ ()
  63.               (define r (proc x))
  64.               (return/pipe r)))))
  65.  
  66. ;; Pipe primitives ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  67.  
  68. (: done (All (I O) (Pipe I O Void)))
  69. (define done (Done (void)))
  70.  
  71. (: yield (All (O) (O -> (All (I) (Pipe I O Void)))))
  72. (define (yield out) (Yield out done))
  73.  
  74. (: await (All (I O) (Pipe I O I)))
  75. (define await (Await Done))
  76.  
  77. ;; A helper function
  78.  
  79. (: absurd (Nothing -> (All (A) A)))
  80. (define (absurd n)
  81.   (error "I can't believe you made it this far"))
  82.  
  83. ;; Running pipes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  84.  
  85. (: simulate/pipe
  86.    (All (I O R A) ((Pipe I O R) (-> I) (O -> Void) (R -> A) -> A)))
  87. (define (simulate/pipe p on-await on-yield on-done)
  88.   (define (go n)
  89.         (simulate/pipe n on-await on-yield on-done))
  90.   (match p
  91.     [(Done result)    (on-done result)]
  92.     [(Effect thunk)   (go (thunk))]
  93.     [(Yield out next) (begin (on-yield out) (go next))]
  94.     [(Await next/f)   (go (next/f (on-await)))]))
  95.  
  96. (: eval/pipe (All (O R) ((Pipe Void O R) -> (Values (Listof O) R))))
  97. (define (eval/pipe p)
  98.   (define outs (box empty))
  99.   (define (on-yield out)
  100.     (set-box! outs (cons out (unbox outs))))
  101.   (define (on-done result)
  102.     (values (unbox outs) result))
  103.   (simulate/pipe p void on-yield on-done))
  104.  
  105. (: run/pipe ((Pipe Void Nothing Void) -> Void))
  106. (define (run/pipe p)
  107.   (simulate/pipe p void absurd void))
  108.  
  109. ;; Composing pipes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  110.  
  111. (: compose/pipe (All (I X O R) ((Pipe X O R) (Pipe I X R) -> (Pipe I O R))))
  112. (define (compose/pipe p1 p2)
  113.   (match p1
  114.     [(Done result)    (Done result)]
  115.     [(Effect thunk)   (Effect (λ () (compose/pipe (thunk) p2)))]
  116.     [(Yield out next) (Yield out (compose/pipe next p2))]
  117.     [(Await next/f1)
  118.      (match p2
  119.        [(Done result)    (Done result)]
  120.        [(Effect thunk)   (Effect (λ () (compose/pipe p1 (thunk))))]
  121.        [(Yield out next) (compose/pipe (next/f1 out) next)]
  122.        [(Await next/f2)  (Await (λ (x) (compose/pipe p1 (next/f2 x))))]
  123.        )]
  124.     ))
  125.  
  126. (define (compose*/pipe . ps)
  127.   (match ps
  128.     [(list) done]
  129.     [(list p) p]
  130.     [(list-rest p1 p2 p-rest)
  131.      (apply compose*/pipe (cons (compose/pipe p1 p2) p-rest))]))
  132.  
  133. ;; A few simple pipes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  134.  
  135. (: id/pipe (All (I) (Conduit I I)))
  136. (define id/pipe (forever/pipe (bind/pipe await yield)))
  137.  
  138. (: list->pipe (All (O) ((Listof O) -> (Source O))))
  139. (define (list->pipe xs)
  140.   (match xs
  141.     [(list) done]
  142.     [(cons y ys)
  143.      (begin/pipe
  144.        (yield y)
  145.        (list->pipe ys))]))
  146.  
  147. (: printer (All (I) (Sink I)))
  148. (define printer (forever/pipe (bind/pipe await (lift./pipe print))))
  149.  
  150. (: func->pipe (All (I O) ((I -> O) -> (Conduit I O))))
  151. (define (func->pipe f)
  152.   (forever/pipe (bind/pipe await (compose yield f))))
  153.  
  154. (: add1/pipe (Conduit Integer Integer))
  155. (define add1/pipe (func->pipe add1))
  156.  
  157. ;; A few simple test runs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  158.  
  159. ;; compose/pipe is associative
  160. (run/pipe
  161.  (compose/pipe printer (compose/pipe add1/pipe (list->pipe '(1 2 3)))))
  162. (printf "\n")
  163. (run/pipe
  164.  (compose/pipe (compose/pipe printer add1/pipe) (list->pipe '(1 2 3))))
  165. (printf "\n")
  166.  
  167.  
  168. ;; id/pipe is the identity of composition
  169. (run/pipe
  170.  (compose*/pipe printer add1/pipe (list->pipe '(1 2 3))))
  171. (printf "\n")
  172. (run/pipe
  173.  (compose*/pipe id/pipe printer
  174.                 id/pipe add1/pipe
  175.                 id/pipe (list->pipe '(1 2 3))
  176.                 id/pipe))
  177. (printf "\n")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement