aboutsummaryrefslogtreecommitdiff
path: root/stdlib/test/test/lux/control/continuation.lux
blob: dfe93023ab0f01c020cce86f2559c12523c3e363 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
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<Cont>
               (^open "&/.") &.Monad<Cont>]
         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<Cont>
                                             [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<Cont>
                                [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<Cont>
                                [[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<Cont>
                        (^open "L/.") (list.Equivalence<List> number.Equivalence<Nat>)
                        visit (: (-> (List Nat)
                                     (&.Cont (List Nat) (List Nat)))
                                 (function (visit xs)
                                   (case xs
                                     #.Nil
                                     (&/wrap #.Nil)

                                     (#.Cons x xs')
                                     (do &.Monad<Cont>
                                       [output (&.shift (function (_ k)
                                                          (do @
                                                            [tail (k xs')]
                                                            (wrap (#.Cons x tail)))))]
                                       (visit output)))))]
                    (L/= elems
                         (&.run (&.reset (visit elems))))
                    ))
            ))))