packages feed

glazier 0.11.0.0 → 0.11.0.1

raw patch · 4 files changed

+25/−186 lines, 4 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Glazier.Example: Action :: a -> Action a
- Glazier.Example: ConsAction :: a -> ConsAction a
- Glazier.Example: Reset :: Reset
- Glazier.Example: Set :: a -> Set a
- Glazier.Example: Tail :: Tail
- Glazier.Example: [getAction] :: Action a -> a
- Glazier.Example: [getConsAction] :: ConsAction a -> a
- Glazier.Example: [getSet] :: Set a -> a
- Glazier.Example: _Action :: AsAction s a => Prism' s (Action a)
- Glazier.Example: _ConsAction :: AsConsAction s a => Prism' s (ConsAction a)
- Glazier.Example: _Reset :: AsReset s => Prism' s Reset
- Glazier.Example: _Set :: AsSet s a => Prism' s (Set a)
- Glazier.Example: _Tail :: AsTail s => Prism' s Tail
- Glazier.Example: class AsAction s a | s -> a
- Glazier.Example: class AsConsAction s a | s -> a
- Glazier.Example: class AsReset s
- Glazier.Example: class AsSet s a | s -> a
- Glazier.Example: class AsTail s
- Glazier.Example: data Reset
- Glazier.Example: data Tail
- Glazier.Example: indexedExample :: (Monoid v, Monoid c, Field2 b b a a, Field1 b b (Index (t s)) (Index (t s)), Ixed (t s), Semigroup v, Semigroup c, AsAction b (t s -> t s), IxValue (t s) ~ s, Monad m, Traversable t) => (WindowT s m v, GadgetT a s m c) -> (WindowT (t s) m v, GadgetT b (t s) m c)
- Glazier.Example: instance Glazier.Example.AsAction (Glazier.Example.Action a) a
- Glazier.Example: instance Glazier.Example.AsConsAction (Glazier.Example.ConsAction a) a
- Glazier.Example: instance Glazier.Example.AsReset Glazier.Example.Reset
- Glazier.Example: instance Glazier.Example.AsSet (Glazier.Example.Set a) a
- Glazier.Example: instance Glazier.Example.AsTail Glazier.Example.Tail
- Glazier.Example: listExample :: (Monoid v, Monoid c, Semigroup v, Semigroup c, AsTail a, AsConsAction a s, AsAction a ([s] -> [s]), Monad m) => Prism' b a -> (WindowT s m v, GadgetT a s m c) -> (WindowT [s] m v, GadgetT b [s] m c)
- Glazier.Example: newtype Action a
- Glazier.Example: newtype ConsAction a
- Glazier.Example: newtype Set a
- Glazier.Example: optionalExample :: (Monoid c, Monoid v, Semigroup c, Semigroup v, AsSet a s, AsReset a, AsAction a (Maybe s -> Maybe s), Monad m) => Prism' a a' -> (WindowT s m v, GadgetT a' s m c) -> (WindowT (Maybe s) m v, GadgetT a (Maybe s) m c)

Files

glazier.cabal view
@@ -1,14 +1,14 @@ name:                glazier-version:             0.11.0.0-synopsis:            Composable widgets framework-description:         Please see README.md+version:             0.11.0.1+synopsis:            Composable widgets framework with enhanced with transformers and lens.+description:         Elm-like Action/Model/View/Update framework powered by typeclasses, monad transformers, and lens. homepage:            https://github.com/louispan/glazier#readme license:             BSD3 license-file:        LICENSE author:              Louis Pan maintainer:          louis@pan.me copyright:           2016 Louis Pan-category:            FRP+category:            FRP, GUI build-type:          Simple cabal-version:       >=1.10 tested-with:         GHC == 8.0.1@@ -16,7 +16,6 @@ library   hs-source-dirs:      src   exposed-modules:     Glazier-                       Glazier.Example                        Glazier.Gadget                        Glazier.Window   build-depends:       base >= 4.7 && < 5
src/Glazier.hs view
@@ -1,3 +1,24 @@+-- Functional version of Elm Action/Model/View/Update architecture, but additionally powered by Haskell typeclasses, monad transformers, and lens.+-- #Features+-- ## Composable widgets+-- Larger widgets can be made out of smaller widgets without changing any existing code, or "lifting of" states.+-- ## Easily embed widget+-- Use of lens and prisms to embed a smaller widget Action &Model within larger widget Action & Model.+-- ## Typeclasses and Monad Transformers+-- Using Haskell typeclasses and monad transformer enables a disciplined and lawful way of composing widgets and effects together.+-- ## Orthogonal wiring+-- Unlike other GUI frameworks, the signal framework (how the widgets interact with other stateful effects) are not fixed by this library. I recommend using the pipe ecosystem, but you could probably use conduit or manually run the StateT transformer yourself.+-- ## Combine multiple concurrent stateful effects+-- I recommend using the pipe ecosystem the signal framework because [pipes-fluid](https://github.com/louispan/pipes-fluid) allows combining multiple concurrent stateful effects whilst maintaining a single source of truth. This is possible because the stateful effects are running over [STM](http://chimera.labs.oreilly.com/books/1230000000929/ch10.html) which will ensure a consistent ordering of stateful effects. Haskell is+-- ## Isolation of IO+-- The  stateful effects are pure and do not involve IO. All IO effects are isolated to an interpreter of the command output of the gadget. This has the benefit of allowing better testing of the intention of gadgets; increasing confidence of the behaviour of the gadget,  reducing the surface area of IO misbehaviour.+-- # Examples+-- ## TodoMVC+-- This is a fully featured TodoMVC in in Haskell and ReactJS using the [glazier-react](https://github.com/louispan/glazier-react) library.+-- For a live demo, see https://louispan.github.io/glazier-react-examples/+-- For more details, see the [todo example README.md](https://github.com/louispan/glazier-react-examples/tree/master/examples/todo)+-- # Slides+-- See [slides](https://github.com/louispan/glazier-react-intro) module Glazier     ( module Glazier.Window     , module Glazier.Gadget
− src/Glazier/Example.hs
@@ -1,159 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE TypeFamilies #-}---- | This contains examples of general widget transformation functions.-module Glazier.Example where--import Control.Category-import Control.Lens-import Control.Monad.Reader-import Data.Foldable-import Data.List-import Data.Semigroup-import Glazier-import Prelude hiding (id, (.))--newtype Action a = Action { getAction :: a }-class AsAction s a | s -> a where-  _Action :: Prism' s (Action a)-instance AsAction (Action a) a where-  _Action = id--newtype ConsAction a = ConsAction { getConsAction :: a }-class AsConsAction s a | s -> a where-  _ConsAction :: Prism' s (ConsAction a)-instance AsConsAction (ConsAction a) a where-  _ConsAction = id--data Reset = Reset-class AsReset s where-  _Reset :: Prism' s Reset-instance AsReset Reset where-  _Reset = id--data Tail = Tail-class AsTail s where-  _Tail :: Prism' s Tail-instance AsTail Tail where-  _Tail = id--newtype Set a = Set  { getSet :: a }-class AsSet s a | s -> a where-  _Set :: Prism' s (Set a)-instance AsSet (Set a) a where-  _Set = id---- | Transforms a widget into an optional widget.--- This wraps the original model inside a Maybe.--- The new action is now a sum type that contains the additional actions:--- * A Reset action--- * A Set action--- * A mapping action--- * The original action--- The original action is wrapped using the given prism and will only--- modify the state if the preview of the prism is not Nothing.--- The view will be mempty if the model is Nothing.--- Widget was a w s m c v--- Widget s v m a c-optionalExample ::-  ( Monoid c-  , Monoid v-  , Semigroup c-  , Semigroup v-  , AsSet a s-  , AsReset a-  , AsAction a (Maybe s -> Maybe s)-  , Monad m-  )-  => Prism' a a' -> (WindowT s m v, GadgetT a' s m c) -> (WindowT (Maybe s) m v, GadgetT a (Maybe s) m c)-optionalExample p (w, g) = (w', g')-  where-    w' = magnify _Just w-    g' =   magnify p (zoom _Just g) -- original action will only work if model is Just-        -- new action handlers-        <> magnify _Set    (review _GadgetT $ \a _ -> pure (mempty, Just $ getSet a))-        <> magnify _Action (review _GadgetT $ \(Action f) s -> pure (mempty, f s))-        <> magnify _Reset  (review _GadgetT $ \_ _ -> pure (mempty, Nothing))---- | Transforms a widget into an list widget.--- Given a separator rendering widget, and a widget,--- this wraps the original model inside a list.--- The new action is now a sum type that contains the additional actions:--- * A Tail action--- * A Cons action--- * A mapping action--- * The original action--- The original action is wrapped using the given prism and will only--- modify the state of the head.--- The view will be mempty if Nil.-listExample ::-  ( Monoid v-  , Monoid c-  , Semigroup v-  , Semigroup c-  , AsTail a-  , AsConsAction a s-  , AsAction a ([s] -> [s])-  , Monad m-  )-  => Prism' b a -> (WindowT s m v, GadgetT a s m c) -> (WindowT [s] m v, GadgetT b [s] m c)-listExample p (WindowT d, g) = (w', g')-  where-     -- Create a list rendering function by-     -- sequencing the View from the original widget.-    w' = WindowT . ReaderT $ \ss -> do-                        ss' <- traverse (runReaderT d) ss-                        pure (fold ss')-    g' = magnify p (-            zoom (ix 0) g -- original action will only work on the head of list-            -- new action handlers-            <> magnify _Tail       (review _GadgetT $ \_ s -> pure (mempty, tail s))-            <> magnify _ConsAction (review _GadgetT $ \(ConsAction a) s -> pure (mempty, a : s))-            <> magnify _Action     (review _GadgetT $ \(Action f) s -> pure (mempty, f s))-        )---- | Transforms a widget into an dictionary widget.--- Given a ordering function, a key function, and a separator rendering function,--- allows a dictionary of k to Widget.--- The new action is now a sum type that contains the additional actions:--- * A mapping action--- * A tuple of (key, original action)--- The original action is now a tuple with an additional key, which will act on the widget if the key exists in the map.-indexedExample ::-  ( Monoid v-  , Monoid c-  , Field2 b b a a-  , Field1 b b (Index (t s)) (Index (t s))-  , Ixed (t s)-  , Semigroup v-  , Semigroup c-  , AsAction b (t s -> t s)-  , IxValue (t s) ~ s-  , Monad m-  , Traversable t-  )-  => (WindowT s m v, GadgetT a s m c) -> (WindowT (t s) m v, GadgetT b (t s) m c)-indexedExample (WindowT d, g) = (w', g')-  where-     -- Create a rendering function by folding the original view function-    w' = WindowT . ReaderT $ \ss -> do-                        ss' <- traverse (runReaderT d) ss-                        pure (fold ss')--    -- This effectively dispatches the Update-    -- ie the action type has changed-    -- so a @dispatch prism@ is not required-    g' = (do-             x <- ask-             let k = x ^. _1-                 -- a = x ^. _2-             -- run u but for a state implanted by ix k-             zoom (ix k) (magnify _2 g)-         )-         <> magnify _Action     (review _GadgetT $ \(Action f) s -> pure (mempty, f s))
src/Glazier/Window.hs view
@@ -9,28 +9,6 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} --- | Functional version of (Elm View/Update & startApp architecture) enabling composable widgets, and a FRP-like framework.------ This framework makes it easier to modularize the Elm architecture idea of View/Update:--- based on the deprecated Elm Architecture version of Jan 2016--- https://github.com/evancz/elm-architecture-tutorial/tree/de5682a5a8e4459aed4637533adb25e462f8a2ae------ The Elm View/Update 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 Window and Gadget resulting in instances can be be composed together into larger Widgets.--- Original inspiration from https://arianvp.me/lenses-and-prisms-for-modular-clientside-apps/--- module Glazier.Window where  import Control.Applicative