Shpadoinkle-0.3.0.0: A programming model for declarative, high performance user interface.

Safe HaskellNone
LanguageHaskell2010

Shpadoinkle.Core

Contents

Description

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

Base Types

newtype Html m a Source #

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.

Constructors

Html 

Fields

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.

Instance details

Defined in Shpadoinkle.Core

Methods

mapC :: (Continuation m a -> Continuation m b) -> Html m a -> Html m b Source #

Applicative m => Functor EndoIso EndoIso (Html m :: Type -> Type) Source #

Html m is a functor in the EndoIso category, where the objects are types and the morphisms are EndoIsos.

Instance details

Defined in Shpadoinkle.Core

Methods

map :: EndoIso a b -> EndoIso (Html m a) (Html m b) Source #

IsString (Html m a) Source #

Strings are overloaded as HTML text nodes: "hiya" = TextNode "hiya"

Instance details

Defined in Shpadoinkle.Core

Methods

fromString :: String -> Html m a Source #

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.

Constructors

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 RawNode target, and the RawEvent, and may perform a monadic action such as a side effect. This is the one and only place where you may introduce a custom monadic action. The JSM to compute the Continuation must be synchronous and non-blocking; otherwise race conditions may result from a Pure Continuation which sets the state based on a previous state captured by the closure. Such Continuations must be executed synchronously during event propagation, and that may not be the case if the code to compute the Continuation of some listener is blocking.

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.

Instance details

Defined in Shpadoinkle.Core

Methods

mapC :: (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: "active" = ("className", PText "active")

Instance details

Defined in Shpadoinkle.Core

Methods

fromString :: String -> [(Text, Prop m a)] Source #

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.

Instance details

Defined in Shpadoinkle.Core

Methods

map :: EndoIso a b -> EndoIso (Prop m a) (Prop m b) Source #

Eq (Prop m a) Source # 
Instance details

Defined in Shpadoinkle.Core

Methods

(==) :: Prop m a -> Prop m a -> Bool Source #

(/=) :: Prop m a -> Prop m a -> Bool Source #

IsString (Prop m a) Source #

Strings are overloaded as text props: ("id", "foo") = ("id", PText "foo")

Instance details

Defined in Shpadoinkle.Core

Methods

fromString :: String -> Prop m a Source #

newtype Props m a Source #

Constructors

Props 

Fields

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.

Instance details

Defined in Shpadoinkle.Core

Methods

mapC :: (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.

Instance details

Defined in Shpadoinkle.Core

Methods

map :: EndoIso a b -> EndoIso (Props m a) (Props m b) Source #

Applicative m => Semigroup (Props m a) Source # 
Instance details

Defined in Shpadoinkle.Core

Methods

(<>) :: Props m a -> Props m a -> Props m a Source #

sconcat :: NonEmpty (Props m a) -> Props m a Source #

stimes :: Integral b => b -> Props m a -> Props m a Source #

Applicative m => Monoid (Props m a) Source # 
Instance details

Defined in Shpadoinkle.Core

Methods

mempty :: Props m a Source #

mappend :: Props m a -> Props m a -> Props m a Source #

mconcat :: [Props m a] -> Props m a Source #

fromProps :: Props m a -> [(Text, Prop m a)] Source #

toProps :: Applicative m => [(Text, Prop m a)] -> Props m a Source #

Prop Constructors

dataProp :: JSVal -> Prop m a Source #

Create a data property.

textProp :: Text -> Prop m a Source #

Create a text property.

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.

baked :: JSM (RawNode, STM (Continuation m a)) -> Html m a Source #

Construct a Potato from a JSM action producing a RawNode.

text :: Text -> Html m a Source #

Construct a text node.

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 TextNodes or Potatoes.

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

newtype RawNode Source #

A DOM node reference. Useful for building baked potatoes and binding a Backend view to the page

Constructors

RawNode 

Fields

newtype RawEvent Source #

A raw event object reference

Constructors

RawEvent 

Fields

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

Associated Types

type VNode b m Source #

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.

Methods

interpret Source #

Arguments

:: (m ~> JSM)

Natural transformation for some m to JSM (this is how a Backend gets access to JSM to perform the rendering side effects)

-> Html (b m) a

Html to interpret

-> 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.

patch Source #

Arguments

:: 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 Nothing on the first run.

-> 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 VNode the effect produces will be passed as the previous Virtual DOM on the next render.

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.

type (~>) m n = forall a. m a -> n a Source #

Natural Transformation

The Shpadoinkle Primitive

shpadoinkle Source #

Arguments

:: 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

type JSM = IO Source #

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

type MonadJSM = MonadIO Source #

The MonadJSM is to JSM what MonadIO is to IO. When using GHCJS it is MonadIO.

askJSM :: MonadJSM m => m JSContextRef Source #

Gets the JavaScript context from the monad

runJSM :: MonadIO m => JSM a -> JSContextRef -> m a Source #

Runs a JSM JavaScript function in a given JavaScript context.

class MonadIO m => MonadUnliftIO (m :: Type -> Type) where Source #

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

The third is a currently nameless law which ensures that the current context is preserved.

  • askUnliftIO >>= (u -> liftIO (unliftIO u m)) = m

If you have a name for this, please submit it in a pull request for great glory.

Since: unliftio-core-0.1.0.0

Minimal complete definition

askUnliftIO | withRunInIO

Methods

askUnliftIO :: m (UnliftIO m) Source #

Capture the current monadic context, providing the ability to run monadic actions in IO.

See UnliftIO for an explanation of why we need a helper datatype here.

Since: unliftio-core-0.1.0.0

withRunInIO :: ((forall a. m a -> IO a) -> IO b) -> m b Source #

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 
Instance details

Defined in Control.Monad.IO.Unlift

Methods

askUnliftIO :: IO (UnliftIO IO) Source #

withRunInIO :: ((forall a. IO a -> IO a) -> IO b) -> IO b Source #

MonadUnliftIO m => MonadUnliftIO (IdentityT m) 
Instance details

Defined in Control.Monad.IO.Unlift

Methods

askUnliftIO :: IdentityT m (UnliftIO (IdentityT m)) Source #

withRunInIO :: ((forall a. IdentityT m a -> IO a) -> IO b) -> IdentityT m b Source #

MonadUnliftIO m => MonadUnliftIO (ReaderT r m) 
Instance details

Defined in Control.Monad.IO.Unlift

Methods

askUnliftIO :: ReaderT r m (UnliftIO (ReaderT r m)) Source #

withRunInIO :: ((forall a. ReaderT r m a -> IO a) -> IO b) -> ReaderT r m b Source #

newtype UnliftIO (m :: Type -> Type) Source #

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

Constructors

UnliftIO 

Fields

liftJSM :: MonadJSM m => JSM a -> m a Source #

The liftJSM is to JSM what liftIO is to IO. When using GHCJS it is liftIO.

writeTVar :: TVar a -> a -> STM () Source #

Write the supplied value into a TVar.

readTVar :: TVar a -> STM a Source #

Return the current value stored in a TVar.

data STM a Source #

A monad supporting atomic memory transactions.

Instances
Monad STM

Since: base-4.3.0.0

Instance details

Defined in GHC.Conc.Sync

Methods

(>>=) :: STM a -> (a -> STM b) -> STM b Source #

(>>) :: STM a -> STM b -> STM b Source #

return :: a -> STM a Source #

fail :: String -> STM a Source #

Functor STM

Since: base-4.3.0.0

Instance details

Defined in GHC.Conc.Sync

Methods

fmap :: (a -> b) -> STM a -> STM b Source #

(<$) :: a -> STM b -> STM a Source #

Applicative STM

Since: base-4.8.0.0

Instance details

Defined in GHC.Conc.Sync

Methods

pure :: a -> STM a Source #

(<*>) :: STM (a -> b) -> STM a -> STM b Source #

liftA2 :: (a -> b -> c) -> STM a -> STM b -> STM c Source #

(*>) :: STM a -> STM b -> STM b Source #

(<*) :: STM a -> STM b -> STM a Source #

Alternative STM

Since: base-4.8.0.0

Instance details

Defined in GHC.Conc.Sync

Methods

empty :: STM a Source #

(<|>) :: STM a -> STM a -> STM a Source #

some :: STM a -> STM [a] Source #

many :: STM a -> STM [a] Source #

MonadPlus STM

Since: base-4.3.0.0

Instance details

Defined in GHC.Conc.Sync

Methods

mzero :: STM a Source #

mplus :: STM a -> STM a -> STM a Source #

data TVar a Source #

Shared memory locations that support atomic memory transactions.

Instances
Eq (TVar a)

Since: base-4.8.0.0

Instance details

Defined in GHC.Conc.Sync

Methods

(==) :: TVar a -> TVar a -> Bool Source #

(/=) :: TVar a -> TVar a -> Bool Source #

modifyTVar :: TVar a -> (a -> a) -> STM () Source #

Mutate the contents of a TVar. N.B., this version is non-strict.

Since: stm-2.3

atomically :: MonadIO m => STM a -> m a #

newTVarIO :: MonadIO m => a -> m (TVar a) #

readTVarIO :: MonadIO m => TVar a -> m a #