| Copyright | (C) 2016-2026 David M. Johnson |
|---|---|
| License | BSD3-style (see the file LICENSE) |
| Maintainer | David M. Johnson <code@dmj.io> |
| Stability | experimental |
| Portability | non-portable |
| Safe Haskell | Safe-Inferred |
| Language | Haskell2010 |
Miso.Effect
Description
Synopsis
- type Effect parent model action = RWS (ComponentInfo parent) [Schedule action] model ()
- type Sub action = Sink action -> IO ()
- type Sink action = action -> IO ()
- type DOMRef = JSVal
- data ComponentInfo parent = ComponentInfo {}
- type ComponentId = Int
- mkComponentInfo :: ComponentId -> ComponentId -> DOMRef -> ComponentInfo parent
- data Schedule action = Schedule Synchronicity (Sink action -> IO ())
- data Synchronicity
- (<#) :: model -> IO action -> Effect parent model action
- (#>) :: IO action -> model -> Effect parent model action
- batch :: [IO action] -> Effect parent model action
- batch_ :: [IO ()] -> Effect parent model action
- io :: IO action -> Effect parent model action
- io_ :: IO () -> Effect parent model action
- sync :: IO action -> Effect parent model action
- sync_ :: IO () -> Effect parent model action
- for :: Foldable f => IO (f action) -> Effect parent model action
- issue :: action -> Effect parent model action
- withSink :: (Sink action -> IO ()) -> Effect parent model action
- mapSub :: (a -> b) -> Sub a -> Sub b
- noop :: action -> Effect parent model action
- beforeAll :: IO () -> Effect parent model action -> Effect parent model action
- afterAll :: IO () -> Effect parent model action -> Effect parent model action
- modifyAllIO :: (IO () -> IO ()) -> Effect parent model action -> Effect parent model action
- componentInfoDOMRef :: Lens (ComponentInfo parent) DOMRef
- componentInfoParentId :: Lens (ComponentInfo parent) ComponentId
- componentInfoId :: Lens (ComponentInfo parent) ComponentId
- runEffect :: Effect parent model action -> ComponentInfo parent -> model -> (model, [Schedule action])
Effect
Types
type Effect parent model action = RWS (ComponentInfo parent) [Schedule action] model () Source #
A monad for succinctly expressing model transitions in the update function.
Effect is a RWS, where the State allows modification to model.
It's also a Writer Monad, where the accumulator is a list of scheduled
IO actions. Multiple actions can be scheduled using tell
from the mtl library and a single asynchronous action can be scheduled using io_.
An Effect represents the results of an update action.
It consists of the updated model and a list of subscriptions. Each Sub is
run in a new thread so there is no risk of accidentally blocking the
application.
Tip: use the Effect monad in combination with the stateful Miso.Lens
operators (all operators ending in "="). The following example assumes
the lenses field1, counter and field2 are in scope and that the
LambdaCase language extension is enabled:
myComponent = Component
{ update = \case
MyAction1 -> do
field1 .= value1
counter += 1
MyAction2 -> do
field2 %= f
io_ $ do
consoleLog "Hello"
consoleLog "World!"
, ...
}
type Sub action = Sink action -> IO () Source #
Type synonym for constructing subscriptions.
For example usage see Miso.Subscription
The Sink function is used to write to the global event queue.
type Sink action = action -> IO () Source #
Function to write to the global event queue for processing by the scheduler.
data ComponentInfo parent Source #
This is the 'Reader r' in Effect. Accessible via ask. It holds
a phantom type for parent. This is used as a witness when calling the
parent function. It gives access to Component metadata such as the DOMRef the
Component was mounted on and the ComponentId associated with it.
Constructors
| ComponentInfo | |
type ComponentId = Int Source #
ComponentId of the current Component
Arguments
| :: ComponentId | |
| -> ComponentId |
|
| -> DOMRef | |
| -> ComponentInfo parent |
Smart constructor for ComponentInfo
IO
Represents a scheduled Effect that is executed either synchronously
or asynchronously.
All IO is by default asynchronous, use the sync function for synchronous
execution. Beware sync can block the render thread for a specific
Component.
N.B. During Component unmounting, all effects are evaluated
synchronously.
Since: 1.9.0.0
Constructors
| Schedule Synchronicity (Sink action -> IO ()) |
data Synchronicity Source #
Type to indicate if effects should be handled asynchronously or synchronously.
Instances
| Show Synchronicity Source # | |
Defined in Miso.Effect Methods showsPrec :: Int -> Synchronicity -> ShowS # show :: Synchronicity -> String # showList :: [Synchronicity] -> ShowS # | |
| Eq Synchronicity Source # | |
Defined in Miso.Effect Methods (==) :: Synchronicity -> Synchronicity -> Bool # (/=) :: Synchronicity -> Synchronicity -> Bool # | |
Combinators
(<#) :: model -> IO action -> Effect parent model action infixl 0 Source #
Smart constructor for an Effect with exactly one action.
(#>) :: IO action -> model -> Effect parent model action infixr 0 Source #
Effect smart constructor, flipped
batch_ :: [IO ()] -> Effect parent model action Source #
Like batch but actions are discarded
Since: 1.9.0.0
Like io but doesn't cause an action to be dispatched to
the update function.
This is handy for scheduling IO computations where you don't care
about their results or when they complete.
Note: The result of IO a is discarded.
Since: 1.9.0.0
Like sync, except discards the result.
Since: 1.9.0.0
Arguments
| :: action |
|
| -> Effect parent model action |
Issue a new action to be processed by update.
data Action = HelloWorld type Model = Int 'update' :: Action -> 'Effect' parent Model Action 'update' = \\case Click -> 'issue' HelloWorld
Since: 1.9.0.0
Arguments
| :: (Sink action -> IO ()) | Callback function that provides access to the underlying |
| -> Effect parent model action |
withSink allows users to write to the global event queue. This is useful for introducing IO into the system.
A synonym for tell, specialized to Effect.
A use-case is scheduling an IO computation which creates a 3rd-party JS
widget which has an associated callback. The callback can then call the sink
to turn events into actions.
'update' FetchJSON = 'withSink' $ \sink -> getJSON (sink . ReceivedJSON) (sink . HandleError)
Since: 1.9.0.0
beforeAll :: IO () -> Effect parent model action -> Effect parent model action Source #
Performs the given IO action before all IO actions collected by the given
effect.
Example usage:
-- delays connecting a websocket by 100000 microseconds beforeAll (liftIO $ threadDelay 100000) $ websocketConnectJSON OnConnect OnClose OnOpen OnError
afterAll :: IO () -> Effect parent model action -> Effect parent model action Source #
Performs the given IO action after all IO actions collected by the given
effect.
Example usage:
-- log that running the a websocket Effect completed afterAll (consoleLog "Done running websocket effect") $ websocketConnectJSON OnConnect OnClose OnOpen OnError
modifyAllIO :: (IO () -> IO ()) -> Effect parent model action -> Effect parent model action Source #
Lens
componentInfoDOMRef :: Lens (ComponentInfo parent) DOMRef Source #
componentInfoParentId :: Lens (ComponentInfo parent) ComponentId Source #
Lens for accessing the parents's ComponentId from ComponentInfo.
update = case
SomeAction -> do
compParentId <- view componentParentId
someAction compParentId
Since: 1.9.0.0
componentInfoId :: Lens (ComponentInfo parent) ComponentId Source #
Lens for accessing the ComponentId from ComponentInfo.
update = case
SomeAction -> do
compId <- view componentInfoId
someAction compId
Since: 1.9.0.0