aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/control/lazy.lux
blob: 50f18e0ddf13b08a91f9222a1d8af20c264c41ae (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
(.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]
                             (is (-> [] a)
                                 generator)
                             (is (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)))