aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/test/lux/control/continuation.lux
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/source/test/lux/control/continuation.lux')
-rw-r--r--stdlib/source/test/lux/control/continuation.lux77
1 files changed, 77 insertions, 0 deletions
diff --git a/stdlib/source/test/lux/control/continuation.lux b/stdlib/source/test/lux/control/continuation.lux
new file mode 100644
index 000000000..0dbbe7dc5
--- /dev/null
+++ b/stdlib/source/test/lux/control/continuation.lux
@@ -0,0 +1,77 @@
+(.module:
+ [lux #*
+ [control
+ ["M" monad (#+ do Monad)]
+ ["&" continuation]]
+ [data
+ ["." number]
+ [collection
+ ["." list]]]
+ ["r" math/random]]
+ lux/test)
+
+(context: "Continuations"
+ (<| (times 100)
+ (do @
+ [sample r.nat
+ #let [(^open "&/.") &.apply
+ (^open "&/.") &.monad]
+ elems (r.list 3 r.nat)]
+ ($_ seq
+ (test "Can run continuations to compute their values."
+ (n/= sample (&.run (&/wrap sample))))
+
+ (test "Can use functor."
+ (n/= (inc sample) (&.run (&/map inc (&/wrap sample)))))
+
+ (test "Can use apply."
+ (n/= (inc sample) (&.run (&/apply (&/wrap inc) (&/wrap sample)))))
+
+ (test "Can use monad."
+ (n/= (inc sample) (&.run (do &.monad
+ [func (wrap inc)
+ arg (wrap sample)]
+ (wrap (func arg))))))
+
+ (test "Can use the current-continuation as a escape hatch."
+ (n/= (n/* 2 sample)
+ (&.run (do &.monad
+ [value (&.call/cc
+ (function (_ k)
+ (do @
+ [temp (k sample)]
+ ## If this code where to run,
+ ## the output would be
+ ## (n/* 4 sample)
+ (k temp))))]
+ (wrap (n/* 2 value))))))
+
+ (test "Can use the current-continuation to build a time machine."
+ (n/= (n/+ 100 sample)
+ (&.run (do &.monad
+ [[restart [output idx]] (&.portal [sample 0])]
+ (if (n/< 10 idx)
+ (restart [(n/+ 10 output) (inc idx)])
+ (wrap output))))))
+
+ (test "Can use delimited continuations with shifting."
+ (let [(^open "&/.") &.monad
+ (^open "L/.") (list.equivalence number.equivalence)
+ visit (: (-> (List Nat)
+ (&.Cont (List Nat) (List Nat)))
+ (function (visit xs)
+ (case xs
+ #.Nil
+ (&/wrap #.Nil)
+
+ (#.Cons x xs')
+ (do &.monad
+ [output (&.shift (function (_ k)
+ (do @
+ [tail (k xs')]
+ (wrap (#.Cons x tail)))))]
+ (visit output)))))]
+ (L/= elems
+ (&.run (&.reset (visit elems))))
+ ))
+ ))))