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

Shpadoinkle.Core

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

data Html :: (Type -> Type) -> Type -> Type where 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.

Constructors

Node :: Text -> [(Text, Prop m a)] -> [Html m a] -> Html m a

A standard node in the DOM tree

Potato :: JSM RawNode -> Html m a

If you can bake an element into a RawNode then you can embed it as a baked potato. Backend does not provide any state management or abstraction to deal with custom embedded content; it's on you to decide how and when this RawNode will be updated. For example, if you wanted to embed a Google map as a baked potato, and you are driving your Backend view with a TVar, you would need to build the RawNode for this map outside of your Backend view and pass it in as an argument. The RawNode is a reference you control.

TextNode :: Text -> Html m a

The humble text node

Instances

Instances details
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 :: forall (m :: Type -> Type) a b. (Continuation m a -> Continuation m b) -> Html m a -> Html m b Source #

Monad 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 :: forall (a :: α) (b :: α). EndoIso a b -> EndoIso (Html m a) (Html m b) #

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 #

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

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

Instance details

Defined in Shpadoinkle.Core

Methods

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

Monad 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 :: forall (a :: α) (b :: α). EndoIso a b -> EndoIso (Prop m a) (Prop m b) #

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 #

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 :: Monad m => Text -> m (a -> a) -> (Text, Prop m a) Source #

Construct a listener from its name and a simple monadic event handler.

listenM_ :: Monad 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 -> Html m a Source #

Construct a Potato from a JSM action producing a RawNode.

text :: Text -> Html m a Source #

Construct a text node.

Html Lenses

props :: Applicative f => ([(Text, Prop m a)] -> f [(Text, Prop m a)]) -> Html m a -> f (Html m a) Source #

Lens to props

children :: Applicative f => ([Html m a] -> f [Html m a]) -> Html m a -> f (Html m a) Source #

Lens to children

name :: Applicative f => (Text -> f Text) -> Html m a -> f (Html m a) Source #

Lens to tag name

textContent :: Applicative f => (Text -> f Text) -> Html m a -> f (Html m a) Source #

Lens to content of TextNodes

Hoists

hoistHtml :: Functor m => Functor n => (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 -> 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.

mapChildren :: ([Html m a] -> [Html m a]) -> Html m a -> Html m a Source #

Transform the children 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 :: Monad 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

Instances

Instances details
ToJSVal RawNode Source # 
Instance details

Defined in Shpadoinkle.Core

FromJSVal RawNode Source # 
Instance details

Defined in Shpadoinkle.Core

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

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

-> a

What is the initial state?

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

data JSM a #

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

Instances details
Monad JSM 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

(>>=) :: JSM a -> (a -> JSM b) -> JSM b #

(>>) :: JSM a -> JSM b -> JSM b #

return :: a -> JSM a #

Functor JSM 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

fmap :: (a -> b) -> JSM a -> JSM b #

(<$) :: a -> JSM b -> JSM a #

MonadFix JSM 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

mfix :: (a -> JSM a) -> JSM a #

MonadFail JSM 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

fail :: String -> JSM a #

Applicative JSM 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

pure :: a -> JSM a #

(<*>) :: JSM (a -> b) -> JSM a -> JSM b #

liftA2 :: (a -> b -> c) -> JSM a -> JSM b -> JSM c #

(*>) :: JSM a -> JSM b -> JSM b #

(<*) :: JSM a -> JSM b -> JSM a #

MonadIO JSM 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

liftIO :: IO a -> JSM a #

MonadThrow JSM 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

throwM :: Exception e => e -> JSM a #

MonadCatch JSM 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

catch :: Exception e => JSM a -> (e -> JSM a) -> JSM a #

MonadMask JSM 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

mask :: ((forall a. JSM a -> JSM a) -> JSM b) -> JSM b #

uninterruptibleMask :: ((forall a. JSM a -> JSM a) -> JSM b) -> JSM b #

generalBracket :: JSM a -> (a -> ExitCase b -> JSM c) -> (a -> JSM b) -> JSM (b, c) #

MonadJSM JSM 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

liftJSM' :: JSM a -> JSM a #

MonadRef JSM 
Instance details

Defined in Language.Javascript.JSaddle.Types

Associated Types

type Ref JSM :: Type -> Type #

Methods

newRef :: a -> JSM (Ref JSM a) #

readRef :: Ref JSM a -> JSM a #

writeRef :: Ref JSM a -> a -> JSM () #

modifyRef :: Ref JSM a -> (a -> a) -> JSM () #

modifyRef' :: Ref JSM a -> (a -> a) -> JSM () #

MonadAtomicRef JSM 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

atomicModifyRef :: Ref JSM a -> (a -> (a, b)) -> JSM b #

atomicModifyRef' :: Ref JSM a -> (a -> (a, b)) -> JSM b #

MonadUnliftIO JSM 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

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

type Ref JSM 
Instance details

Defined in Language.Javascript.JSaddle.Types

type Ref JSM = Ref IO

class (Applicative m, MonadIO m) => MonadJSM (m :: Type -> Type) #

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

Instances

Instances details
MonadJSM JSM 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

liftJSM' :: JSM a -> JSM a #

MonadJSM m => MonadJSM (MaybeT m) 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

liftJSM' :: JSM a -> MaybeT m a #

MonadJSM m => MonadJSM (ListT m) 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

liftJSM' :: JSM a -> ListT m a #

MonadJSM m => MonadJSM (IdentityT m) 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

liftJSM' :: JSM a -> IdentityT m a #

MonadJSM m => MonadJSM (ExceptT e m) 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

liftJSM' :: JSM a -> ExceptT e m a #

(Error e, MonadJSM m) => MonadJSM (ErrorT e m) 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

liftJSM' :: JSM a -> ErrorT e m a #

MonadJSM m => MonadJSM (StateT s m) 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

liftJSM' :: JSM a -> StateT s m a #

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

Defined in Language.Javascript.JSaddle.Types

Methods

liftJSM' :: JSM a -> ReaderT r m a #

MonadJSM m => MonadJSM (StateT s m) 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

liftJSM' :: JSM a -> StateT s m a #

(Monoid w, MonadJSM m) => MonadJSM (WriterT w m) 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

liftJSM' :: JSM a -> WriterT w m a #

(Monoid w, MonadJSM m) => MonadJSM (WriterT w m) 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

liftJSM' :: JSM a -> WriterT w m a #

MonadJSM m => MonadJSM (ContT r m) 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

liftJSM' :: JSM a -> ContT r m a #

(Monoid w, MonadJSM m) => MonadJSM (RWST r w s m) 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

liftJSM' :: JSM a -> RWST r w s m a #

(Monoid w, MonadJSM m) => MonadJSM (RWST r w s m) 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

liftJSM' :: JSM a -> RWST r w s m a #

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

Methods

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

Instances details
MonadUnliftIO IO 
Instance details

Defined in Control.Monad.IO.Unlift

Methods

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

MonadUnliftIO JSM 
Instance details

Defined in Language.Javascript.JSaddle.Types

Methods

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

MonadUnliftIO m => MonadUnliftIO (IdentityT m) 
Instance details

Defined in Control.Monad.IO.Unlift

Methods

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

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

Defined in Control.Monad.IO.Unlift

Methods

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

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

Constructors

UnliftIO 

Fields

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

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

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

Write the supplied value into a TVar.

readTVar :: TVar a -> STM a #

Return the current value stored in a TVar.

data STM a #

A monad supporting atomic memory transactions.

Instances

Instances details
Monad STM

Since: base-4.3.0.0

Instance details

Defined in GHC.Conc.Sync

Methods

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

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

return :: a -> STM a #

Functor STM

Since: base-4.3.0.0

Instance details

Defined in GHC.Conc.Sync

Methods

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

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

Applicative STM

Since: base-4.8.0.0

Instance details

Defined in GHC.Conc.Sync

Methods

pure :: a -> STM a #

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

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

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

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

Alternative STM

Since: base-4.8.0.0

Instance details

Defined in GHC.Conc.Sync

Methods

empty :: STM a #

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

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

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

MonadPlus STM

Since: base-4.3.0.0

Instance details

Defined in GHC.Conc.Sync

Methods

mzero :: STM a #

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

MonadRef STM 
Instance details

Defined in Control.Monad.Ref

Associated Types

type Ref STM :: Type -> Type #

Methods

newRef :: a -> STM (Ref STM a) #

readRef :: Ref STM a -> STM a #

writeRef :: Ref STM a -> a -> STM () #

modifyRef :: Ref STM a -> (a -> a) -> STM () #

modifyRef' :: Ref STM a -> (a -> a) -> STM () #

MonadAtomicRef STM 
Instance details

Defined in Control.Monad.Ref

Methods

atomicModifyRef :: Ref STM a -> (a -> (a, b)) -> STM b #

atomicModifyRef' :: Ref STM a -> (a -> (a, b)) -> STM b #

type Ref STM 
Instance details

Defined in Control.Monad.Ref

type Ref STM = TVar

data TVar a #

Shared memory locations that support atomic memory transactions.

Instances

Instances details
Eq (TVar a)

Since: base-4.8.0.0

Instance details

Defined in GHC.Conc.Sync

Methods

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

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

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

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

Lifted version of newTVarIO

Since: unliftio-0.2.1.0

retrySTM :: STM a #

Renamed retry for unqualified export

Since: unliftio-0.2.1.0

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

Lifted version of atomically

Since: unliftio-0.2.1.0