Advertisement
kenpusney

loop_with_yield.ml

May 18th, 2023
1,450
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
OCaml 2.29 KB | None | 0 0
  1. open Effect
  2. open Effect.Shallow
  3.  
  4. type 'a t += Recur : 'a -> 'b t | Yield : 'a -> unit t | Return : 'a -> 'a t
  5.  
  6. let recur a = perform (Recur a)
  7. let yield a = perform (Yield a)
  8. let return a = perform (Return a)
  9.  
  10. type ('a, 'b) state = Finished | NotStarted | Running of ('a, 'b) continuation
  11.  
  12. let loop : 'a -> ('a -> 'b) -> unit -> 'b option =
  13.  fun init fn ->
  14.   let state' = ref NotStarted in
  15.   let rec helper : 'a -> unit -> 'b option =
  16.    fun input () ->
  17.     match !state' with
  18.     | NotStarted ->
  19.         state' := Running (fiber fn);
  20.         helper init ()
  21.     | Finished -> None
  22.     | Running k ->
  23.         continue_with k input
  24.           {
  25.             retc =
  26.               (fun _ ->
  27.                 state' := Finished;
  28.                 helper input ());
  29.             exnc = (fun e -> raise e);
  30.             effc =
  31.               (fun (type b) (eff : b t) ->
  32.                 match eff with
  33.                 | Recur value ->
  34.                     Some
  35.                       (fun (_ : (b, _) continuation) ->
  36.                         state' := Running (fiber fn);
  37.                         helper (Obj.magic value) ())
  38.                 | Yield value ->
  39.                     Some
  40.                       (fun (k : (b, _) continuation) ->
  41.                         state' := Running (Obj.magic k);
  42.                         Some (Obj.magic value))
  43.                 | Return value ->
  44.                     Some
  45.                       (fun (_ : (b, _) continuation) ->
  46.                         state' := Finished;
  47.                         Some (Obj.magic value))
  48.                 | _ -> None);
  49.           }
  50.   in
  51.   helper init
  52.  
  53. let loopwith init fn = loop init fn ()
  54.  
  55. let rec runloop f loop =
  56.   match loop () with
  57.   | Some x ->
  58.       f x;
  59.       runloop f loop
  60.   | None -> ()
  61.  
  62. let compose f g x = f (g x)
  63.  
  64. let fact i =
  65.   loopwith (i, 1) (fun (iter, acc) ->
  66.       if iter > 0 then recur (iter - 1, iter * acc, 1) else return acc)
  67.  
  68. let print_optional = function
  69.   | Some x -> print_endline (string_of_int x)
  70.   | None -> print_endline "None"
  71.  
  72. let count n =
  73.   let counter =
  74.     loop 0 (fun i ->
  75.         if i < n then (
  76.           yield i;
  77.           recur (i + 1))
  78.         else return i)
  79.   in
  80.   runloop (compose print_endline string_of_int) counter
  81.  
  82. let () =
  83.   print_optional (fact 5);
  84.   count 5
  85.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement