miso
Copyright(C) 2016-2025 David M. Johnson
LicenseBSD3-style (see the file LICENSE)
MaintainerDavid M. Johnson <code@dmj.io>
Stabilityexperimental
Portabilitynon-portable
Safe HaskellNone
LanguageHaskell2010

Miso.Effect

Description

This module defines Effect, Sub and Sink types, which are used to define update function and subs field of the Component.

Synopsis

Effect

Types

type Effect model action = RWS ComponentName [Sink action -> JSM ()] model () Source #

A monad for succinctly expressing model transitions in the update function.

Effect is a RWS, where the State abstracts over manually passing the model around. 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 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 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
          putStrLn "Hello"
          putStrLn "World!"
  , ...
  }

type Sub action = Sink action -> JSM () Source #

Type synonym for constructing event subscriptions.

The Sink callback is used to dispatch actions which are then fed back into the update function.

type Sink action = action -> JSM () Source #

Function to asynchronously dispatch actions to the update function.

Combinators

(<#) :: model -> JSM action -> Effect model action infixl 0 Source #

Smart constructor for an Effect with exactly one action.

(#>) :: JSM action -> model -> Effect model action infixr 0 Source #

Effect smart constructor, flipped

batch :: [JSM action] -> Effect model action Source #

Smart constructor for an Effect with multiple actions.

batch_ :: [JSM ()] -> Effect model action Source #

Like batch but action are discarded

io :: JSM action -> Effect model action Source #

Schedule a single IO action for later execution.

Note that multiple IO action can be scheduled using tell from the mtl library.

io_ :: JSM () -> Effect model action Source #

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.

for :: Foldable f => JSM (f action) -> Effect model action Source #

Like io but generalized to any instance of Foldable

This is handy for scheduling IO computations that return a Maybe value

issue :: action -> Effect model action Source #

Issue a new Action to be processed by update.

update :: Action -> Effect Model Action
update = \case
  Click -> issue HelloWorld

Since: 1.9.0.0

withSink :: (Sink action -> JSM ()) -> Effect model action Source #

withSink allows users to access the sink of the Component or top-level Component in their application. 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. To do this without accessing a sink requires going via a Subscription which introduces a leaky-abstraction.

update FetchJSON = withSink $ \sink -> getJSON (sink . ReceivedJSON) (sink . HandleError)

mapSub :: (a -> b) -> Sub a -> Sub b Source #

Turn a Sub that consumes actions of type a into a Sub that consumes actions of type b using the supplied function of type a -> b.

Internal

runEffect :: Effect model action -> MisoString -> model -> (model, [Sink action -> JSM ()]) Source #

Internal function used to unwrap an EffectCore

Deprecated

scheduleIO :: JSM action -> Effect model action Source #

Deprecated: Please use io instead

scheduleIO_ :: JSM () -> Effect model action Source #

Deprecated: Please use io_ instead

scheduleIOFor_ :: Foldable f => JSM (f action) -> Effect model action Source #

Deprecated: Please use for instead

scheduleSub :: (Sink action -> JSM ()) -> Effect model action Source #

Deprecated: Please use withSink instead

effectSub :: model -> (Sink action -> JSM ()) -> Effect model action Source #

Deprecated: Please use put and withSink instead

batchEff :: model -> [JSM action] -> Effect model action Source #

Deprecated: Please use put and batch instead

noEff :: model -> Effect model action Source #

Deprecated: Please use put instead