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

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
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 :: (Functor m, Functor n) => (Continuation m a -> Continuation n b) -> Html m a -> Html n 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 :: 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

PText :: Text -> Prop m a

A text property

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.

PFlag :: Bool -> Prop m a

A boolean property works as a flag: for example ("disabled", PFlag False) has no effect, while ("disabled", PFlag True) will add the disabled attribute.

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 :: (Functor m, Functor n) => (Continuation m a -> Continuation n b) -> Prop m a -> Prop n 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 :: 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

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.

flagProp :: Bool -> Prop m a Source #

Create a boolean property.

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 -> (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 => (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 :: (Text -> b) -> ((RawNode -> RawEvent -> JSM (Continuation m a)) -> b) -> (Bool -> 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

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?

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

Convenience Variants

runJSorWarp :: Int -> JSM () -> IO () Source #

Start the program!

This function works in GHC and GHCjs. I saved you from using C preprocessor directly. You're welcome.

fullPage Source #

Arguments

:: Backend b m a 
=> Monad (b m) 
=> Eq a 
=> (m ~> JSM)

How do we get to JSM?

-> (TVar a -> b m ~> m)

What backend are we running?

-> a

What is the initial state?

-> (a -> Html (b m) a)

How should the html look?

-> b m RawNode

Where do we render?

-> JSM () 

Wrapper around shpadoinkle for full page apps that do not need outside control of the territory

fullPageJSM Source #

Arguments

:: Backend b JSM a 
=> Monad (b JSM) 
=> Eq a 
=> (TVar a -> b JSM ~> JSM)

What backend are we running?

-> a

What is the initial state?

-> (a -> Html (b JSM) a)

How should the html look?

-> b JSM RawNode

Where do we render?

-> JSM () 

fullPageJSM is a wrapper around shpadoinkle for full page apps that do not need outside control of the territory, where actions are performed directly in JSM.

This set of assumptions is extremely common when starting a new project.

simple Source #

Arguments

:: Backend b JSM a 
=> Monad (b JSM) 
=> Eq a 
=> (TVar a -> b JSM ~> JSM)

What backend are we running?

-> a

what is the initial state?

-> (a -> Html (b JSM) a)

how should the html look?

-> b JSM RawNode

where do we render?

-> JSM () 

Simple app

(a good starting place)

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

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

askUnliftIO :: JSM (UnliftIO JSM) #

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

data TVar a #

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 #

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

PrimUnlifted (TVar a)

Since: primitive-0.6.4.0

Instance details

Defined in Data.Primitive.UnliftedArray

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

Lifted version of newTVarIO

Since: unliftio-0.2.1.0

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

Lifted version of readTVarIO

Since: unliftio-0.2.1.0