aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/control/io.lux
blob: bcb0f4d8c80db4e79f4cfac58a862369d352acad (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
(.module:
  {#.doc "A method for abstracting I/O and effectful computations to make it safe while writing pure functional code."}
  [library
   [lux #*
    [abstract
     [functor (#+ Functor)]
     [apply (#+ Apply)]
     [monad (#+ Monad do)]]
    [control
     [parser
      ["s" code]]]
    [type
     abstract]
    [macro (#+ with_identifiers)
     [syntax (#+ syntax:)]
     ["." template]]]])

(abstract: .public (IO a)
  {#.doc "A type that represents synchronous, effectful computations that may interact with the outside world."}

  (-> Any a)

  (def: label
    (All [a] (-> (-> Any a) (IO a)))
    (|>> :abstraction))

  (template: (!io computation)
    [(:abstraction (template.with_locals [g!func g!arg]
                     (function (g!func g!arg)
                       computation)))])

  (template: (run!' io)
    ... creatio ex nihilo
    [((:representation io) [])])

  (syntax: .public (io computation)
    {#.doc (example "Delays the evaluation of an expression, by wrapping it in an IO 'thunk'."
                    "Great for wrapping effectful computations (which will not be performed until the IO is 'run!')."
                    (io (exec
                          (log! msg)
                          "Some value...")))}
    (with_identifiers [g!func g!arg]
      (in (list (` ((~! ..label) (function ((~ g!func) (~ g!arg))
                                   (~ computation))))))))

  (def: .public run!
    {#.doc "A way to execute IO computations and perform their side-effects."}
    (All [a] (-> (IO a) a))
    (|>> run!'))

  (implementation: .public functor
    (Functor IO)
    
    (def: (map f)
      (|>> run!' f !io)))

  (implementation: .public apply
    (Apply IO)
    
    (def: &functor ..functor)

    (def: (apply ff fa)
      (!io ((run!' ff) (run!' fa)))))

  (implementation: .public monad
    (Monad IO)
    
    (def: &functor ..functor)

    (def: in (|>> !io))
    
    (def: join (|>> run!' run!' !io)))
  )