Safe Haskell | None |
---|---|
Language | Haskell2010 |
Shpadoinkle is an abstract frontend programming model, with one-way data flow, and a single source of truth. This module provides a parsimonious implementation of Shpadoinkle with few implementation details.
Synopsis
- newtype Html m a = Html {}
- data Prop :: (Type -> Type) -> Type -> Type where
- newtype Props m a = Props {}
- fromProps :: Props m a -> [(Text, Prop m a)]
- toProps :: Applicative m => [(Text, Prop m a)] -> Props m a
- dataProp :: JSVal -> Prop m a
- flagProp :: Bool -> Prop m a
- textProp :: Text -> Prop m a
- listenerProp :: (RawNode -> RawEvent -> JSM (Continuation m a)) -> Prop m a
- bakedProp :: (RawNode -> JSM (STM (Continuation m a))) -> Prop m a
- listenRaw :: Text -> (RawNode -> RawEvent -> JSM (Continuation m a)) -> (Text, Prop m a)
- listen :: Text -> (a -> a) -> (Text, Prop m a)
- listenM :: Applicative m => Text -> m (a -> a) -> (Text, Prop m a)
- listenM_ :: Applicative m => Text -> m () -> (Text, Prop m a)
- listenC :: Text -> Continuation m a -> (Text, Prop m a)
- listener :: Continuation m a -> Prop m a
- h :: Text -> [(Text, Prop m a)] -> [Html m a] -> Html m a
- baked :: JSM (RawNode, STM (Continuation m a)) -> Html m a
- text :: Text -> Html m a
- hoistHtml :: Functor m => (m ~> n) -> Html m a -> Html n a
- hoistProp :: Functor m => (m ~> n) -> Prop m a -> Prop n a
- cataH :: (Text -> [(Text, Prop m a)] -> [b] -> b) -> (JSM (RawNode, STM (Continuation m a)) -> b) -> (Text -> b) -> Html m a -> b
- cataProp :: (JSVal -> b) -> (Text -> b) -> (Bool -> b) -> ((RawNode -> RawEvent -> JSM (Continuation m a)) -> b) -> ((RawNode -> JSM (STM (Continuation m a))) -> b) -> Prop m a -> b
- mapProps :: ([(Text, Prop m a)] -> [(Text, Prop m a)]) -> Html m a -> Html m a
- injectProps :: [(Text, Prop m a)] -> Html m a -> Html m a
- eitherH :: Applicative m => (a -> Html m a) -> (b -> Html m b) -> Either a b -> Html m (Either a b)
- newtype RawNode = RawNode {}
- newtype RawEvent = RawEvent {
- unRawEvent :: JSVal
- class Backend b m a | b m -> a where
- type (~>) m n = forall a. m a -> n a
- shpadoinkle :: forall b m a. Backend b m a => Monad (b m) => Eq a => (m ~> JSM) -> (TVar a -> b m ~> m) -> TVar a -> (a -> Html (b m) a) -> b m RawNode -> JSM ()
- data JSM a
- class (Applicative m, MonadIO m) => MonadJSM (m :: Type -> Type)
- askJSM :: MonadJSM m => m JSContextRef
- runJSM :: MonadIO m => JSM a -> JSContextRef -> m a
- class MonadIO m => MonadUnliftIO (m :: Type -> Type) where
- withRunInIO :: ((forall a. m a -> IO a) -> IO b) -> m b
- newtype UnliftIO (m :: Type -> Type) = UnliftIO {}
- liftJSM :: MonadJSM m => JSM a -> m a
- writeTVar :: TVar a -> a -> STM ()
- readTVar :: TVar a -> STM a
- data STM a
- data TVar a
- modifyTVar :: TVar a -> (a -> a) -> STM ()
- readTVarIO :: MonadIO m => TVar a -> m a
- newTVarIO :: MonadIO m => a -> m (TVar a)
- retrySTM :: STM a
- atomically :: MonadIO m => STM a -> m a
Base Types
This is the core type in Backend. Please note, this is NOT the Virtual DOM used by Backend. This type backs a DSL that is then interpreted into Virtual DOM by the Backend of your choosing. HTML comments are not supported. This is Church encoded for performance reasons.
Instances
Continuous Html Source # | Given a lens, you can change the type of an Html by using the lens to convert the types of the Continuations inside it. |
Defined in Shpadoinkle.Core mapC :: forall (m :: Type -> Type) a b. (Continuation m a -> Continuation m b) -> Html m a -> Html m b Source # | |
Applicative m => Functor EndoIso EndoIso (Html m :: Type -> Type) Source # |
|
IsString (Html m a) Source # | Strings are overloaded as HTML text nodes:
|
Defined in Shpadoinkle.Core fromString :: String -> Html m a # |
data Prop :: (Type -> Type) -> Type -> Type where Source #
Properties of a DOM node. Backend does not use attributes directly, but rather is focused on the more capable properties that may be set on a DOM node in JavaScript. If you wish to add attributes, you may do so by setting its corresponding property.
PData :: JSVal -> Prop m a | A data property, these do NOT appear in static rendering |
PText :: Text -> Prop m a | A text property |
PFlag :: Bool -> Prop m a | A boolean property |
PPotato :: (RawNode -> JSM (STM (Continuation m a))) -> Prop m a | Bake a custom property The STM Monad will be called recursively. The semantics here is roughly an event stream of continuations. |
PListener :: (RawNode -> RawEvent -> JSM (Continuation m a)) -> Prop m a | Event listeners are provided with the |
Instances
Continuous Prop Source # | Given a lens, you can change the type of a Prop by using the lens to convert the types of the Continuations which it contains if it is a listener. |
Defined in Shpadoinkle.Core mapC :: forall (m :: Type -> Type) a b. (Continuation m a -> Continuation m b) -> Prop m a -> Prop m b Source # | |
IsString [(Text, Prop m a)] Source # | Strings are overloaded as the class property:
|
Defined in Shpadoinkle.Core fromString :: String -> [(Text, Prop m a)] # | |
Applicative m => Functor EndoIso EndoIso (Prop m :: Type -> Type) Source # | Prop is a functor in the EndoIso category, where the objects are types and the morphisms are EndoIsos. |
Eq (Prop m a) Source # | |
IsString (Prop m a) Source # | Strings are overloaded as text props:
|
Defined in Shpadoinkle.Core fromString :: String -> Prop m a # |
Instances
Continuous Props Source # | Given a lens, you can change the type of a Props by using the lens to convert the types of the Continuations inside. |
Defined in Shpadoinkle.Core mapC :: forall (m :: Type -> Type) a b. (Continuation m a -> Continuation m b) -> Props m a -> Props m b Source # | |
Applicative m => Functor EndoIso EndoIso (Props m :: Type -> Type) Source # | Props is a functor in the EndoIso category, where the objects are types and the morphisms are EndoIsos. |
Applicative m => Semigroup (Props m a) Source # | |
Applicative m => Monoid (Props m a) Source # | |
Prop Constructors
listenerProp :: (RawNode -> RawEvent -> JSM (Continuation m a)) -> Prop m a Source #
Create an event listener property.
bakedProp :: (RawNode -> JSM (STM (Continuation m a))) -> Prop m a Source #
Create a delicious proptato.
Listeners
listenRaw :: Text -> (RawNode -> RawEvent -> JSM (Continuation m a)) -> (Text, Prop m a) Source #
Construct a listener from its name and an event handler.
listen :: Text -> (a -> a) -> (Text, Prop m a) Source #
Construct a listener from its Text
name and an output value.
listenM :: Applicative m => Text -> m (a -> a) -> (Text, Prop m a) Source #
Construct a listener from its name and a simple monadic event handler.
listenM_ :: Applicative m => Text -> m () -> (Text, Prop m a) Source #
Construct a listener from its name and a simple stateless monadic event handler.
listenC :: Text -> Continuation m a -> (Text, Prop m a) Source #
Construct a listener from its name and an event handler.
listener :: Continuation m a -> Prop m a Source #
Construct a simple listener property that will perform an action.
Html Constructors
h :: Text -> [(Text, Prop m a)] -> [Html m a] -> Html m a Source #
Construct an HTML element JSX-style.
Hoists
hoistHtml :: Functor m => (m ~> n) -> Html m a -> Html n a Source #
If you can provide a Natural Transformation from one Functor to another
then you may change the action of Html
.
hoistProp :: Functor m => (m ~> n) -> Prop m a -> Prop n a Source #
If you can provide a Natural Transformation from one Functor to another
then you may change the action of Prop
.
Catamorphisms
cataH :: (Text -> [(Text, Prop m a)] -> [b] -> b) -> (JSM (RawNode, STM (Continuation m a)) -> b) -> (Text -> b) -> Html m a -> b Source #
Fold an HTML element, i.e. transform an h-algebra into an h-catamorphism.
cataProp :: (JSVal -> b) -> (Text -> b) -> (Bool -> b) -> ((RawNode -> RawEvent -> JSM (Continuation m a)) -> b) -> ((RawNode -> JSM (STM (Continuation m a))) -> b) -> Prop m a -> b Source #
Transform a p-algebra into a p-catamorphism. This is like polymorphic pattern matching.
Utilities
mapProps :: ([(Text, Prop m a)] -> [(Text, Prop m a)]) -> Html m a -> Html m a Source #
Transform the properties of some Node. This has no effect on TextNode
s or Potato
es.
injectProps :: [(Text, Prop m a)] -> Html m a -> Html m a Source #
Inject props into an existing Node
.
eitherH :: Applicative m => (a -> Html m a) -> (b -> Html m b) -> Either a b -> Html m (Either a b) Source #
Construct an HTML element out of heterogeneous alternatives.
JSVal Wrappers
A DOM node reference. Useful for building baked potatoes and binding a Backend view to the page
Backend Interface
class Backend b m a | b m -> a where Source #
The Backend class describes a backend that can render Html
.
Backends are generally Monad Transformers b
over some Monad m
.
patch raw Nothing >=> patch raw Nothing = patch raw Nothing
VNode type family allows backends to have their own Virtual DOM. As such we can change out the rendering of our Backend view with new backends without updating our view logic.
:: (m ~> JSM) | Natural transformation for some |
-> Html (b m) a |
|
-> b m (VNode b m) | Effect producing the Virtual DOM representation |
A backend must be able to interpret Html
into its own internal Virtual DOM.
:: RawNode | The container for rendering the Backend view |
-> Maybe (VNode b m) | Perhaps there is a previous Virtual DOM to diff against. The value will be |
-> VNode b m | New Virtual DOM to render |
-> b m (VNode b m) | Effect producing an updated Virtual DOM. This is not needed by all backends.
Some JavaScript-based backends need to do this for the next tick. Regardless, whatever
|
A Backend must be able to patch the RawNode
containing the view, with a
new view if the Virtual DOM changed.
setup :: JSM () -> JSM () Source #
A Backend may perform some imperative setup steps.
The Shpadoinkle Primitive
:: forall b m a. Backend b m a | |
=> Monad (b m) | |
=> Eq a | |
=> (m ~> JSM) | How to get to JSM? |
-> (TVar a -> b m ~> m) | What backend are we running? |
-> TVar a | How can we know when to update? |
-> (a -> Html (b m) a) | How should the HTML look? |
-> b m RawNode | Where do we render? |
-> JSM () |
The core view instantiation function combines a backend, a territory, and a model and renders the Backend view to the page.
Re-Exports
The JSM
monad keeps track of the JavaScript execution context.
When using GHCJS it is IO
.
Given a JSM
function and a JSContextRef
you can run the
function like this...
runJSM jsmFunction javaScriptContext
Instances
Monad JSM | |
Functor JSM | |
MonadFix JSM | |
Defined in Language.Javascript.JSaddle.Types | |
MonadFail JSM | |
Defined in Language.Javascript.JSaddle.Types | |
Applicative JSM | |
MonadIO JSM | |
Defined in Language.Javascript.JSaddle.Types | |
MonadThrow JSM | |
Defined in Language.Javascript.JSaddle.Types | |
MonadCatch JSM | |
MonadMask JSM | |
MonadJSM JSM | |
Defined in Language.Javascript.JSaddle.Types | |
MonadRef JSM | |
MonadAtomicRef JSM | |
Defined in Language.Javascript.JSaddle.Types atomicModifyRef :: Ref JSM a -> (a -> (a, b)) -> JSM b # atomicModifyRef' :: Ref JSM a -> (a -> (a, b)) -> JSM b # | |
MonadUnliftIO JSM | |
Defined in Language.Javascript.JSaddle.Types | |
type Ref JSM | |
Defined in Language.Javascript.JSaddle.Types |
class (Applicative m, MonadIO m) => MonadJSM (m :: Type -> Type) #
Instances
askJSM :: MonadJSM m => m JSContextRef #
Gets the JavaScript context from the monad
runJSM :: MonadIO m => JSM a -> JSContextRef -> m a #
Runs a JSM
JavaScript function in a given JavaScript context.
class MonadIO m => MonadUnliftIO (m :: Type -> Type) where #
Monads which allow their actions to be run in IO
.
While MonadIO
allows an IO
action to be lifted into another
monad, this class captures the opposite concept: allowing you to
capture the monadic context. Note that, in order to meet the laws
given below, the intuition is that a monad must have no monadic
state, but may have monadic context. This essentially limits
MonadUnliftIO
to ReaderT
and IdentityT
transformers on top of
IO
.
Laws. For any value u
returned by askUnliftIO
, it must meet the
monad transformer laws as reformulated for MonadUnliftIO
:
unliftIO u . return = return
unliftIO u (m >>= f) = unliftIO u m >>= unliftIO u . f
Instances of MonadUnliftIO
must also satisfy the idempotency law:
askUnliftIO >>= \u -> (liftIO . unliftIO u) m = m
This law showcases two properties. First, askUnliftIO
doesn't change
the monadic context, and second, liftIO . unliftIO u
is equivalent to
id
IF called in the same monadic context as askUnliftIO
.
Since: unliftio-core-0.1.0.0
withRunInIO :: ((forall a. m a -> IO a) -> IO b) -> m b #
Convenience function for capturing the monadic context and running an IO
action with a runner function. The runner function is used to run a monadic
action m
in IO
.
Since: unliftio-core-0.1.0.0
Instances
MonadUnliftIO IO | |
Defined in Control.Monad.IO.Unlift | |
MonadUnliftIO JSM | |
Defined in Language.Javascript.JSaddle.Types | |
MonadUnliftIO m => MonadUnliftIO (IdentityT m) | |
Defined in Control.Monad.IO.Unlift | |
MonadUnliftIO m => MonadUnliftIO (ReaderT r m) | |
Defined in Control.Monad.IO.Unlift |
newtype UnliftIO (m :: Type -> Type) #
The ability to run any monadic action m a
as IO a
.
This is more precisely a natural transformation. We need to new
datatype (instead of simply using a forall
) due to lack of
support in GHC for impredicative types.
Since: unliftio-core-0.1.0.0
A monad supporting atomic memory transactions.
Instances
Monad STM | Since: base-4.3.0.0 |
Functor STM | Since: base-4.3.0.0 |
Applicative STM | Since: base-4.8.0.0 |
Alternative STM | Since: base-4.8.0.0 |
MonadPlus STM | Since: base-4.3.0.0 |
MonadRef STM | |
MonadAtomicRef STM | |
Defined in Control.Monad.Ref atomicModifyRef :: Ref STM a -> (a -> (a, b)) -> STM b # atomicModifyRef' :: Ref STM a -> (a -> (a, b)) -> STM b # | |
type Ref STM | |
Defined in Control.Monad.Ref |
Shared memory locations that support atomic memory transactions.
modifyTVar :: TVar a -> (a -> a) -> STM () #
Mutate the contents of a TVar
. N.B., this version is
non-strict.
Since: stm-2.3
readTVarIO :: MonadIO m => TVar a -> m a #
Lifted version of readTVarIO
Since: unliftio-0.2.1.0
atomically :: MonadIO m => STM a -> m a #
Lifted version of atomically
Since: unliftio-0.2.1.0