Safe Haskell | None |
---|---|
Language | Haskell2010 |
Functional version of (Elm Brief/View & startApp architecture) enabling composable widgets, and a FRP-like framework.
This framework makes it easier to modularize the Elm architecture idea of View/Brief: based on the deprecated Elm Architecture version of Jan 2016 https://github.com/evancz/elm-architecture-tutorial/tree/de5682a5a8e4459aed4637533adb25e462f8a2ae
The Elm View/Brief is basically as follows:
data Model = Blah....
data Action = DoThis | DoThat deriving Show
-- | update is fired from an event processing loop
update :: Action -> Model -> Model
-- | The widget from view
knows how to send Action to a mailbox
view :: Signal Address -> Model -> Html
This module uses isomorphic implementations Brief and View resulting in instances can be be composed together into larger Widgets. Original inspiration from https://arianvp.me/lenses-and-prisms-for-modular-clientside-apps/
This framework provides three main combinators:
* Semigroup and Monoid instances for concatenating widgets.
* dispatch
is used to re-route the action type.
* implant
is used to modify the model type.
- newtype Window m s v = Window {}
- _WindowT :: Iso (Window m s v) (Window m' s' v') (s -> m v) (s' -> m' v')
- _WindowT' :: Iso' (Window m s v) (s -> m v)
- hoistWindow :: Monad m => (forall a. m a -> n a) -> Window m s v -> Window n s v
- type family Implanted m :: * -> *
- class Implant m n s t | m -> s, n -> t, m t -> n, n s -> m where
- type family Dispatched m :: * -> *
- class Dispatch m n b a | m -> b, n -> a, m a -> n, n b -> m where
Documentation
The Elm view function is basically view :: model -> html
NB. elm-html is actually view :: Signal.Address action -> model -> html
where Signal.Address action
is the Pipes.Concurrent.Output that is sent
actions (eg. when html button is clicked).
This address argument is not required in the general case, and is only required for specific widgets on an as needed basis.
Therefore, using the fundamental type of view :: model -> html
This is be ehanced with monadic effects with ReaderT.
This is named Window instead of View to avoid confusion with view from Control.Lens
_WindowT :: Iso (Window m s v) (Window m' s' v') (s -> m v) (s' -> m' v') Source #
This in conjuction with Wrapped instance gives the following functions: liftWindow :: (MonadTrans t, Monad m) => Window m s v -> Window (t m) s v liftWindow = hoistWindow lift
underWindow :: (ReaderT s m v -> ReaderT s' m' v') -> Window m s v -> Window m' s' v' underWindow f = _Wrapping Window %~ f
overWindow :: (Window m s v -> Window m' s' v') -> ReaderT s m v -> ReaderT s' m' v' overWindow f = _Unwrapping Window %~ f
belowWindow :: ((s -> m v) -> (s' -> m' v')) -> Window m s v -> Window m' s' v' belowWindow f = _WindowT %~ f
aboveWindow :: (Window m s v -> Window m' s' v') -> (s -> m v) -> (s' -> m' v') aboveWindow f = from _WindowT %~ f
hoistWindow :: Monad m => (forall a. m a -> n a) -> Window m s v -> Window n s v Source #
NB lift can be simulated: liftWindow :: (MonadTrans t, Monad m) => Window m s v -> Window (t m) s v liftWindow = hoistWindow lift
type family Implanted m :: * -> * Source #
Modify the state given a lens, prism or traversal.
NB. This is Zoom
for Notify.
class Implant m n s t | m -> s, n -> t, m t -> n, n s -> m where Source #
Monad m => Implant (Window m s v) (Window m t v) s t Source # | |
Monad m => Implant (Gadget s m a c) (Gadget t m a c) s t Source # | |
Monad m => Implant (Gadget s m a c) (Gadget t m a c) s t Source # | |
Monad m => Implant (Widget s v m a c) (Widget t v m a c) s t Source # | |
Monad m => Implant (Widget s v m a c) (Widget t v m a c) s t Source # | |
type family Dispatched m :: * -> * Source #
type Dispatched (Gadget s m a c) Source # | |
type Dispatched (Gadget s m a c) Source # | |
type Dispatched (Widget s v m a c) Source # | |
type Dispatched (Widget s v m a c) Source # | |