aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/control/lazy.lux
blob: c96a5f5694fb69549fc1fc5850d158b0a0384d14 (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
(.using
 [library
  [lux (.except)
   [abstract
    [functor (.only Functor)]
    [apply (.only Apply)]
    [monad (.only Monad do)]
    [equivalence (.only Equivalence)]]
   [control
    ["[0]" io]
    [parser
     ["<[0]>" code]]
    [concurrency
     ["[0]" atom]]]
   [macro (.only with_symbols)
    [syntax (.only syntax)]]
   [type (.only sharing)
    [primitive (.except)]]]])

(primitive .public (Lazy a)
  (-> [] a)

  (def: (lazy' generator)
    (All (_ a) (-> (-> [] a) (Lazy a)))
    (let [cache (atom.atom (sharing [a]
                                    (-> [] a)
                                    generator

                                    (Maybe a)
                                    {.#None}))]
      (abstraction (function (_ _)
                     (case (io.run! (atom.read! cache))
                       {.#Some value}
                       value

                       _
                       (let [value (generator [])]
                         (exec
                           (io.run! (atom.compare_and_swap! _ {.#Some value} cache))
                           value)))))))

  (def: .public (value lazy)
    (All (_ a) (-> (Lazy a) a))
    ((representation lazy) [])))

(def: .public lazy
  (syntax (_ [expression <code>.any])
    (with_symbols [g!_]
      (in (list (` ((~! ..lazy') (function ((~ g!_) (~ g!_)) (~ expression)))))))))

(def: .public (equivalence (open "_#[0]"))
  (All (_ a) (-> (Equivalence a) (Equivalence (Lazy a))))
  (implementation
   (def: (= left right)
     (_#= (..value left)
          (..value right)))))

(def: .public functor
  (Functor Lazy)
  (implementation
   (def: (each f fa)
     (lazy (f (value fa))))))

(def: .public apply
  (Apply Lazy)
  (implementation
   (def: functor ..functor)
   (def: (on fa ff)
     (lazy ((value ff) (value fa))))))

(def: .public monad
  (Monad Lazy)
  (implementation
   (def: functor ..functor)
   (def: in (|>> lazy))
   (def: conjoint ..value)))