0 | module Web.MVC.Cmd
  1 |
  2 | import Control.Monad.Either.Extra
  3 | import JS
  4 |
  5 | %default total
  6 |
  7 | --------------------------------------------------------------------------------
  8 | --          Commands
  9 | --------------------------------------------------------------------------------
 10 |
 11 | ||| A `Cmd` (abbreviation of "command") is a (typically effectful) computation
 12 | ||| which might send an arbitrary number of events of type `e` to an event
 13 | ||| handler synchronously or asynchronously.
 14 | |||
 15 | ||| Commands are used as the primary means of setting up (interactive) UI
 16 | ||| components and running effectful computations.
 17 | |||
 18 | ||| Module `Web.MVC.View` provides various commands for creating, modifying
 19 | ||| and deleting interactive DOM elements.
 20 | |||
 21 | ||| Module `Web.MVC.Animate` has commands for firing events at regular
 22 | ||| intervals and for running animations.
 23 | |||
 24 | ||| Module `Web.MVC.Http` has commands for sending requests to and
 25 | ||| firing events upon receiving responses from HTTP servers.
 26 | public export
 27 | record Cmd (e : Type) where
 28 |   constructor C
 29 |   run : (handler : e -> JSIO ()) -> JSIO ()
 30 |
 31 | export %inline
 32 | Functor Cmd where
 33 |   map f (C run) = C $ run . (. f)
 34 |
 35 | export
 36 | Semigroup (Cmd e) where
 37 |   C f <+> C g = C $ \h => f h >> g h
 38 |
 39 | export %inline
 40 | Monoid (Cmd e) where
 41 |   neutral = C . const $ pure ()
 42 |
 43 | ||| Wraps a batch of commands in a single command by
 44 | ||| installing each command sequentially.
 45 | |||
 46 | ||| This function is stack safe.
 47 | export
 48 | batch : List (Cmd e) -> Cmd e
 49 | batch cs = C $ \h => traverseList_ (`run` h) cs
 50 |
 51 | ||| Wrap an effectful computation in a command.
 52 | |||
 53 | ||| The produced result is fired synchronously.
 54 | export %inline
 55 | cmd : JSIO e -> Cmd e
 56 | cmd v = C (v >>=)
 57 |
 58 | ||| Wrap an effectful computation in a command.
 59 | |||
 60 | ||| The produced result is fired synchronously.
 61 | export %inline
 62 | liftIO : IO e -> Cmd e
 63 | liftIO = cmd . liftIO
 64 |
 65 | ||| Wrap an effectful computation in a command.
 66 | |||
 67 | ||| This will never fire an event.
 68 | export %inline
 69 | cmd_ : JSIO () -> Cmd e
 70 | cmd_ v = C $ const v
 71 |
 72 | ||| Wrap an effectful computation in a command.
 73 | |||
 74 | ||| This will never fire an event.
 75 | export %inline
 76 | liftIO_ : IO () -> Cmd e
 77 | liftIO_ = cmd_ . liftIO
 78 |
 79 | ||| Fires the given event once, synchronously.
 80 | export %inline
 81 | pure : e -> Cmd e
 82 | pure v = C (v)
 83 |
 84 | ||| A command that produces no event.
 85 | |||
 86 | ||| This will never fire an event.
 87 | export %inline
 88 | noAction : Cmd e
 89 | noAction = neutral
 90 |
 91 | ||| Use the given command conditionally.
 92 | |||
 93 | ||| If the boolean flag is `False`, this will return the
 94 | ||| empty command (`noAction`).
 95 | export
 96 | cmdIf : Bool -> Lazy (Cmd e) -> Cmd e
 97 | cmdIf True  u = u
 98 | cmdIf False _ = noAction
 99 |
100 | ||| Convert a value in a `Maybe` to a `Cmd e`.
101 | |||
102 | ||| Returns the empty command in case of a `Nothing`.
103 | export
104 | cmdIfJust : Maybe t -> (t -> Cmd e) -> Cmd e
105 | cmdIfJust m f = maybe noAction f m
106 |