Reflex: Front-end development done awesome

Dave Laing

data61

Introduction

What is the virtual DOM?

DOM -> DOM

What is FRP?

  • Precise semantics

  • Supports continuous time

What is Reflex?

  • Precise semantics

  • Discrete time

  • High performance

  • Higher order usage

Getting started

> git clone https://github.com/reflex-frp/reflex-platform

> cd my-cabal-project
> PATH_TO_REFLEX_PLATFORM/work-on ghcjs ./.
> cabal configure --ghcjs

> cd my-cabal-project
> PATH_TO_REFLEX_PLATFORM/work-on ghc ./.
> cabal configure

Event

data Event t a



 

data Event t a

  ~

[(t, a)] 

eOutput = eInput

instance Functor (Event t) where ...

flipColour :: Colour -> Colour
flipColour Red  = Blue
flipColour Blue = Red
eOutput = flipColour <$> eInput

(<$) :: Functor f => a -> f b -> f a

eOutput = Blue <$ eInput

ffilter :: Reflex t
        => (a -> Bool) 
        -> Event t a 
        -> Event t a

isRed :: Colour -> Bool
isRed Red  = True
isRed Blue = False
eOutput = ffilter isRed eInput

fmapMaybe :: Reflex t 
          => (a -> Maybe b) 
          -> Event t a 
          -> Event t b

parseColour :: Text -> Maybe Colour
parseColour "Red"  = Just Red
parseColour "Blue" = Just Blue
parseColour _      = Nothing
eOutput = fmapMaybe parseColour eInput

fmapMaybe    :: Reflex t 
             => (a -> Maybe b)
             -> Event t a
             -> Event t b

fmapMaybe id :: Reflex t 
             => (a -> Maybe b)
             -> Event t a
             -> Event t b

fmapMaybe id :: Reflex t 
             => 
                Event t (Maybe c) 
             -> Event t c

eCount :: Event t Int

eFizz :: Event t Text
eFizz = "Fizz" <$ ffilter ((== 0) . (`mod` 3)) eCount
eBuzz :: Event t Text
eBuzz = "Buzz" <$ ffilter ((== 0) . (`mod` 5)) eCount

eFizz :: Event t Text
eFizz = "Fizz" <$ ffilter ((== 0) . (`mod` 3)) eCount
eBuzz :: Event t Text
eBuzz = "Buzz" <$ ffilter ((== 0) . (`mod` 5)) eCount

leftmost :: [Event t a] -> Event t a

eLeft :: Event t Text
eLeft = leftmost [eFizz, eBuzz]

eInput = leftmost [Red <$ eRed, Blue <$ eBlue]

mergeWith :: (a -> a -> a) -> [Event t a] -> Event t a

eMerge :: Event t Text
eMerge = mergeWith (<>) [eFizz, eBuzz]

instance Semigroup a => Semigroup (Event t a) where ...

eMerge :: Event t Text
eMerge = eFizz <> eBuzz

eFizzBuzz :: Event t Text
eFizzBuzz = leftmost [eFizz <> eBuzz, eCount]

Behavior

data Behavior t a



 

data Behavior t a

  ~

t -> a

hold :: MonadHold t m
     => a
     -> Event t a
     -> m (Behavior t a)

tag :: Reflex t 
    => Behavior t a
    -> Event t b
    -> Event t a

sampleBlue                = do
  bColour <- hold
  

sampleBlue                = do
  bColour <- hold Blue
  

sampleBlue eInput         = do
  bColour <- hold Blue
 

sampleBlue eInput         = do
  bColour <- hold Blue eInput
 

sampleBlue eInput         = do
  bColour <- hold Blue eInput
         tag 

sampleBlue eInput         = do
  bColour <- hold Blue eInput
         tag bColour

sampleBlue eInput eSample = do
  bColour <- hold Blue eInput
         tag bColour

sampleBlue eInput eSample = do
  bColour <- hold Blue eInput
         tag bColour eSample

sampleBlue eInput eSample = do
  bColour <- hold Blue eInput
  pure $ tag bColour eSample

sampleBlue eInput eSample = do
  bColour <- hold Blue eInput
  pure $ tag bColour eSample

sampleBlue eInput eSample = do
  bColour <- hold Blue eInput

  pure $ tag bColour eSample

sampleBlue eInput eSample = do
  bColour <- hold Blue eInput
  let eAny = leftmost [                     ]
  pure $ tag bColour eSample

sampleBlue eInput eSample = do
  bColour <- hold Blue eInput
  let eAny = leftmost [              eSample]
  pure $ tag bColour eSample

sampleBlue eInput eSample = do
  bColour <- hold Blue eInput
  let eAny = leftmost [      eInput, eSample]
  pure $ tag bColour eSample

sampleBlue eInput eSample = do
  bColour <- hold Blue eInput
  let eAny = leftmost [() <$ eInput, eSample]
  pure $ tag bColour eSample

sampleBlue eInput eSample = do
  bColour <- hold Blue eInput
  let eAny = leftmost [() <$ eInput, eSample]
  pure $ tag bColour eAny

sampleBlue eInput eSample = do
  bColour <- hold Blue eInput
  let eAny = leftmost [() <$ eInput, eSample]
  pure $ tag bColour eAny

attach          :: Reflex t 
                => 
                   Behavior t a 
                -> Event t b 
                -> Event t (a, b)

attachWith      :: Reflex t 
                => (a -> b -> c) 
                -> Behavior t a
                -> Event t b
                -> Event t c

attachWithMaybe :: Reflex t
                => (a -> b -> Maybe c) 
                -> Behavior t a
                -> Event t b
                -> Event t c

gate            :: Reflex t 
                => 
                   Behavior t Bool
                -> Event t a
                -> Event t a

instance Functor (Behavior t) where ..

sampleBlue     eInput eSample = do
  bColour <- hold Blue eInput

  pure $ tag        bColour eSample

sampleFlipBlue eInput eSample = do
  bColour <- hold Blue eInput

  pure $ tag        bColour eSample

sampleFlipBlue eInput eSample = do
  bColour <- hold Blue eInput
  let bFlippedColour = flipColour <$> bColour
  pure $ tag        bColour eSample

sampleFlipBlue eInput eSample = do
  bColour <- hold Blue eInput
  let bFlippedColour = flipColour <$> bColour
  pure $ tag bFlippedColour eSample

sampleFlipBlue eInput eSample = do
  bColour <- hold Blue eInput
  let bFlippedColour = flipColour <$> bColour
  pure $ tag bFlippedColour eSample

b <- hold (f initial) (f <$> eChange)
pure b

~

b <- hold initial eChange
pure $ f <$> b

instance Applicative (Behavior t) where ..

sampleBlue       eInput eSample = do
  bColour <- hold    Blue eInput
  pure $ tag bColour     eSample

sampleAlwaysBlue eInput eSample = do
  bColour <- hold    Blue eInput
  pure $ tag bColour     eSample

sampleAlwaysBlue eInput eSample = do
  let bColour = pure Blue
  pure $ tag bColour     eSample

sampleAlwaysBlue eInput eSample = do

  pure $ tag (pure Blue) eSample

sampleAlwaysBlue eInput eSample =

         tag (pure Blue) eSample

sampleAlwaysBlue eInput eSample =

         tag (pure Blue) eSample

sampleBlue eInput          eSample = do
  bColour  <- hold Blue eInput


  pure $ tag bColour                            eSample

samplePair eInput          eSample = do
  bColour  <- hold Blue eInput


  pure $ tag bColour                            eSample

samplePair eInput1         eSample = do
  bColour1 <- hold Blue eInput1


  pure $ tag bColour1                           eSample

samplePair eInput1 eInput2 eSample = do
  bColour1 <- hold Blue eInput1


  pure $ tag bColour1                           eSample

samplePair eInput1 eInput2 eSample = do
  bColour1 <- hold Blue eInput1
  bColour2 <- hold Blue eInput2

  pure $ tag bColour1                           eSample

samplePair eInput1 eInput2 eSample = do
  bColour1 <- hold Blue eInput1
  bColour2 <- hold Blue eInput2
  let bPair = (,) <$> bColour1 <*> bColour2
  pure $ tag bColour1                           eSample

samplePair eInput1 eInput2 eSample = do
  bColour1 <- hold Blue eInput1
  bColour2 <- hold Blue eInput2
  let bPair = (,) <$> bColour1 <*> bColour2
  pure $ tag bPair                              eSample

samplePair eInput1 eInput2 eSample = do
  bColour1 <- hold Blue eInput1
  bColour2 <- hold Blue eInput2

  pure $ tag ((,) <$> bColour1 <*> bColour2)    eSample

samplePair eInput1 eInput2 eSample = do
  bColour1 <- hold Blue eInput1
  bColour2 <- hold Blue eInput2

  pure $      (,) <$> bColour1 <*> bColour2  <@ eSample

samplePair eInput1 eInput2 eSample = do
  bColour1 <- hold Blue eInput1
  bColour2 <- hold Blue eInput2

  pure $      (,) <$> bColour1 <*> bColour2  <@ eSample

instance Reflex t => 
         Monad (Behavior t) where ..
instance (Reflex t, Monoid a) => 
         Monoid (Behavior t a) where ..
instance (Reflex t, Num a) => 
         Num (Behavior t a) where ..
instance (Reflex t, IsString a) => 
         IsString (Behavior t a) where ..

Dynamic

data Dynamic t a



 

data Dynamic t a

  ~ 

(Event t a, Behavior t a) 

updated :: Reflex t 
        => Dynamic t a 
        -> Event t a

current :: Reflex t 
        => Dynamic t a 
        -> Behavior t a

hold        :: (Reflex t, MonadHold t m) 
            => 
               a 
            -> Event t a 
            -> m (Behavior t a)

holdDyn     :: (Reflex t, MonadHold t m) 
            => 
               a 
            -> Event t a 
            -> m (Dynamic  t a)

foldDyn     :: (Reflex t, MonadHold t m, MonadFix m) 
            => (a -> b -> b) 
            -> b 
            -> Event t a 
            -> m (Dynamic  t b)

foldDyn ($) :: (Reflex t, MonadHold t m, MonadFix m) 
            => (a -> b -> b) 
            -> b 
            -> Event t a 
            -> m (Dynamic  t b)

foldDyn ($) :: (Reflex t, MonadHold t m, MonadFix m) 
            => 
               c 
            -> Event t (c -> c)
            -> m (Dynamic  t c)

counter :: (Reflex t, MonadHold t m, MonadFix m) 
        =>

           m (Dynamic t Int)
counter             =



 

counter :: (Reflex t, MonadHold t m, MonadFix m) 
        => Event t ()

        -> m (Dynamic t Int)
counter             =



 

counter :: (Reflex t, MonadHold t m, MonadFix m) 
        => Event t ()

        -> m (Dynamic t Int)
counter eAdd        =



 

counter :: (Reflex t, MonadHold t m, MonadFix m) 
        => Event t ()

        -> m (Dynamic t Int)
counter eAdd        =
  foldDyn ($) 0
  
  
   

counter :: (Reflex t, MonadHold t m, MonadFix m) 
        => Event t ()

        -> m (Dynamic t Int)
counter eAdd        =
  foldDyn ($) 0                 $
      (+ 1)   <$ eAdd
  
   

counter :: (Reflex t, MonadHold t m, MonadFix m) 
        => Event t ()
        -> Event t ()
        -> m (Dynamic t Int)
counter eAdd        =
  foldDyn ($) 0                 $
      (+ 1)   <$ eAdd
  
   

counter :: (Reflex t, MonadHold t m, MonadFix m) 
        => Event t ()
        -> Event t ()
        -> m (Dynamic t Int)
counter eAdd eClear =
  foldDyn ($) 0                 $
      (+ 1)   <$ eAdd
  
   

counter :: (Reflex t, MonadHold t m, MonadFix m) 
        => Event t ()
        -> Event t ()
        -> m (Dynamic t Int)
counter eAdd eClear =
  foldDyn ($) 0 . mergeWith (.) $ [
      (+ 1)   <$ eAdd
  
    ] 

counter :: (Reflex t, MonadHold t m, MonadFix m) 
        => Event t ()
        -> Event t ()
        -> m (Dynamic t Int)
counter eAdd eClear =
  foldDyn ($) 0 . mergeWith (.) $ [
      (+ 1)   <$ eAdd
    , const 0 <$ eClear
    ]

counter :: (Reflex t, MonadHold t m, MonadFix m) 
        => Event t ()
        -> Event t ()
        -> m (Dynamic t Int)
counter eAdd eClear =
  foldDyn ($) 0 . mergeWith (.) $ [
      (+ 1)   <$ eAdd
    , const 0 <$ eClear
    ]

instance Reflex t => 
         Functor (Dynamic t) where ...
instance Reflex t => 
         Applicative (Dynamic t) where ...
instance Reflex t => 
         Monad (Dynamic t) where ...

samplePair :: (Reflex t, MonadHold t m) 
           => Event t Colour
           -> Event t Colour
           -> Event t ()
           -> m (Event    t (Colour, Colour))
samplePair eInput1 eInput2 eSample = do
  bColour1 <- hold    Blue eInput1
  bColour2 <- hold    Blue eInput2
  let bPair = (,) <$> bColour1 <*> bColour2
  pure $ tag bPair eSample

samplePair :: (Reflex t, MonadHold t m) 
           => Event t Colour
           -> Event t Colour

           -> m (Event    t (Colour, Colour))
samplePair eInput1 eInput2         = do
  bColour1 <- hold    Blue eInput1
  bColour2 <- hold    Blue eInput2
  let bPair = (,) <$> bColour1 <*> bColour2
  pure $ tag bPair eSample

samplePair :: (Reflex t, MonadHold t m) 
           => Event t Colour
           -> Event t Colour

           -> m (Event    t (Colour, Colour))
samplePair eInput1 eInput2         = do
  bColour1 <- hold    Blue eInput1
  bColour2 <- hold    Blue eInput2
  let bPair = (,) <$> bColour1 <*> bColour2
 

samplePair :: (Reflex t, MonadHold t m) 
           => Event t Colour
           -> Event t Colour

           -> m (Event    t (Colour, Colour))
samplePair eInput1 eInput2         = do
  bColour1 <- hold    Blue eInput1
  bColour2 <- hold    Blue eInput2
  pure $      (,) <$> bColour1 <*> bColour2
 

samplePair :: (Reflex t, MonadHold t m) 
           => Event t Colour
           -> Event t Colour

           -> m (Behavior t (Colour, Colour))
samplePair eInput1 eInput2         = do
  bColour1 <- hold    Blue eInput1
  bColour2 <- hold    Blue eInput2
  pure $      (,) <$> bColour1 <*> bColour2
 

samplePair :: (Reflex t, MonadHold t m) 
           => Event t Colour
           -> Event t Colour

           -> m (Behavior t (Colour, Colour))
samplePair eInput1 eInput2         = do
  dColour1 <- holdDyn Blue eInput1
  bColour2 <- hold    Blue eInput2
  pure $      (,) <$> bColour1 <*> bColour2
 

samplePair :: (Reflex t, MonadHold t m) 
           => Event t Colour
           -> Event t Colour

           -> m (Behavior t (Colour, Colour))
samplePair eInput1 eInput2         = do
  dColour1 <- holdDyn Blue eInput1
  dColour2 <- holdDyn Blue eInput2
  pure $      (,) <$> bColour1 <*> bColour2
 

samplePair :: (Reflex t, MonadHold t m) 
           => Event t Colour
           -> Event t Colour

           -> m (Behavior t (Colour, Colour))
samplePair eInput1 eInput2         = do
  dColour1 <- holdDyn Blue eInput1
  dColour2 <- holdDyn Blue eInput2
  pure $      (,) <$> dColour1 <*> dColour2
 

samplePair :: (Reflex t, MonadHold t m) 
           => Event t Colour
           -> Event t Colour

           -> m (Dynamic  t (Colour, Colour))
samplePair eInput1 eInput2         = do
  dColour1 <- holdDyn Blue eInput1
  dColour2 <- holdDyn Blue eInput2
  pure $      (,) <$> dColour1 <*> dColour2
 

splitPair :: Reflex t 
          => Dynamic t (Colour, Colour)
          -> (Dynamic t Colour, Dynamic t Colour)
splitPair dPair =
  let
    p1 = fmap fst dPair
    p2 = fmap snd dPair
  in
    (p1, p2)

holdUniqDyn :: (Reflex t, MonadHold t m, MonadFix m, Eq a) 
            => Dynamic t a 
            -> m (Dynamic t a)

splitPair ::  Reflex t 
          => Dynamic t (Colour, Colour)
          ->   (Dynamic t Colour, Dynamic t Colour)
splitPair dPair =
  let
    p1 =               fmap fst dPair
    p2 =               fmap snd dPair
  in     (p1, p2)

splitPair :: (Reflex t, MonadHold t m, MonadFix m)
          => Dynamic t (Colour, Colour)
          ->   (Dynamic t Colour, Dynamic t Colour)
splitPair dPair =
  let
    p1 =               fmap fst dPair
    p2 =               fmap snd dPair
  in     (p1, p2)

splitPair :: (Reflex t, MonadHold t m, MonadFix m)
          => Dynamic t (Colour, Colour)
          -> m (Dynamic t Colour, Dynamic t Colour)
splitPair dPair =
  let
    p1 =               fmap fst dPair
    p2 =               fmap snd dPair
  in     (p1, p2)

splitPair :: (Reflex t, MonadHold t m, MonadFix m)
          => Dynamic t (Colour, Colour)
          -> m (Dynamic t Colour, Dynamic t Colour)
splitPair dPair =
  do
    p1 =               fmap fst dPair
    p2 =               fmap snd dPair
  in     (p1, p2)

splitPair :: (Reflex t, MonadHold t m, MonadFix m)
          => Dynamic t (Colour, Colour)
          -> m (Dynamic t Colour, Dynamic t Colour)
splitPair dPair =
  do
    p1 <- holdUniqDyn (fmap fst dPair)
    p2 =               fmap snd dPair
  in     (p1, p2)

splitPair :: (Reflex t, MonadHold t m, MonadFix m)
          => Dynamic t (Colour, Colour)
          -> m (Dynamic t Colour, Dynamic t Colour)
splitPair dPair =
  do
    p1 <- holdUniqDyn (fmap fst dPair)
    p2 <- holdUniqDyn (fmap snd dPair)
  in     (p1, p2)

splitPair :: (Reflex t, MonadHold t m, MonadFix m)
          => Dynamic t (Colour, Colour)
          -> m (Dynamic t Colour, Dynamic t Colour)
splitPair dPair =
  do
    p1 <- holdUniqDyn (fmap fst dPair)
    p2 <- holdUniqDyn (fmap snd dPair)
    pure (p1, p2)

RecursiveDo


counter :: (Reflex t, MonadFix m, MonadHold t m) 
        => 
           Event t ()
        -> Event t ()
        -> m (Dynamic t Int)
counter        eAdd eClear =  do


  dCount <- foldDyn ($) 0 . mergeWith (.) $ [
      (+ 1)   <$                         eAdd
    , const 0 <$                         eClear
    ]
    
  pure dCount


counter :: (Reflex t, MonadFix m, MonadHold t m) 
        => Dynamic t Int
        -> Event t ()
        -> Event t ()
        -> m (Dynamic t Int)
counter        eAdd eClear =  do


  dCount <- foldDyn ($) 0 . mergeWith (.) $ [
      (+ 1)   <$                         eAdd
    , const 0 <$                         eClear
    ]
    
  pure dCount


counter :: (Reflex t, MonadFix m, MonadHold t m) 
        => Dynamic t Int
        -> Event t ()
        -> Event t ()
        -> m (Dynamic t Int)
counter dLimit eAdd eClear =  do


  dCount <- foldDyn ($) 0 . mergeWith (.) $ [
      (+ 1)   <$                         eAdd
    , const 0 <$                         eClear
    ]
    
  pure dCount


counter :: (Reflex t, MonadFix m, MonadHold t m) 
        => Dynamic t Int
        -> Event t ()
        -> Event t ()
        -> m (Dynamic t Int)
counter dLimit eAdd eClear =  do


  dCount <- foldDyn ($) 0 . mergeWith (.) $ [
      (+ 1)   <$ gate _                  eAdd
    , const 0 <$                         eClear
    ]
    
  pure dCount


counter :: (Reflex t, MonadFix m, MonadHold t m) 
        => Dynamic t Int
        -> Event t ()
        -> Event t ()
        -> m (Dynamic t Int)
counter dLimit eAdd eClear =  do
  let dLimitOK = (<) <$> dCount <*> dLimit

  dCount <- foldDyn ($) 0 . mergeWith (.) $ [
      (+ 1)   <$ gate _                  eAdd
    , const 0 <$                         eClear
    ]
    
  pure dCount


counter :: (Reflex t, MonadFix m, MonadHold t m) 
        => Dynamic t Int
        -> Event t ()
        -> Event t ()
        -> m (Dynamic t Int)
counter dLimit eAdd eClear =  do
  let dLimitOK = (<) <$> dCount <*> dLimit

  dCount <- foldDyn ($) 0 . mergeWith (.) $ [
      (+ 1)   <$ gate (current dLimitOK) eAdd
    , const 0 <$                         eClear
    ]
    
  pure dCount

{-# LANGUAGE RecursiveDo #-}
counter :: (Reflex t, MonadFix m, MonadHold t m) 
        => Dynamic t Int
        -> Event t ()
        -> Event t ()
        -> m (Dynamic t Int)
counter dLimit eAdd eClear =  do
  let dLimitOK = (<) <$> dCount <*> dLimit

  dCount <- foldDyn ($) 0 . mergeWith (.) $ [
      (+ 1)   <$ gate (current dLimitOK) eAdd
    , const 0 <$                         eClear
    ]
    
  pure dCount

{-# LANGUAGE RecursiveDo #-}
counter :: (Reflex t, MonadFix m, MonadHold t m) 
        => Dynamic t Int 
        -> Event t () 
        -> Event t ()
        -> m (Dynamic t Int)
counter dLimit eAdd eClear = mdo
  let dLimitOK = (<) <$> dCount <*> dLimit

  dCount <- foldDyn ($) 0 . mergeWith (.) $ [
      (+ 1)   <$ gate (current dLimitOK) eAdd
    , const 0 <$                         eClear
    ]

  pure dCount

{-# LANGUAGE RecursiveDo #-}
counter :: (Reflex t, MonadFix m, MonadHold t m) 
        => Dynamic t Int 
        -> Event t () 
        -> Event t ()
        -> m (Dynamic t Int)
counter dLimit eAdd eClear = mdo
  let dLimitOK = (<) <$> dCount <*> dLimit

  dCount <- foldDyn ($) 0 . mergeWith (.) $ [
      (+ 1)   <$ gate (current dLimitOK) eAdd
    , const 0 <$                         eClear
    ]

  pure dCount

DomBuilder

el :: DomBuilder t m 
   => Text 
   -> m a 
   -> m a
text :: DomBuilder t m 
     => Text 
     -> m ()

el "div" $
  text "TODO"

button :: DomBuilder t m 
       => Text 
       -> m (Event t ())

todoItem :: MonadWidget t m 
         => Text 
         -> m (Event t ())
todoItem placeholder =
  el "div" $ do
    el "div" $ 
      text placeholder
    button "Remove"

dynText :: (PostBuild t m, DomBuilder t m) 
        => Dynamic t Text 
        -> m ()

el "div" $ mdo



  eRemove <- todoItem "TODO"




  pure ()

el "div" $ mdo



  eRemove <- todoItem "TODO"

  dLabel <- holdDyn "" $ 
    "Removed:" <$ eRemove

  pure ()

el "div" $ mdo
  el "div" $ 
    dynText dLabel

  eRemove <- todoItem "TODO"

  dLabel <- holdDyn "" $ 
    "Removed:" <$ eRemove

  pure ()

el "div" $ mdo
  el "div" $ 
    dynText dLabel

  eRemove <- todoItem "TODO"

  dLabel <- holdDyn "" $ 
    "Removed:" <$ eRemove

  pure ()

elAttr    ::  DomBuilder t m 
          => Text 
          ->            Map Text Text 
          -> m a 
          -> m a

elDynAttr :: (DomBuilder t m, PostBuild t m) 
          => Text 
          -> Dynamic t (Map Text Text) 
          -> m a 
          -> m a

elClass    ::  DomBuilder t m 
           => Text 
           ->           Text 
           -> m a 
           -> m a

elDynClass :: (DomBuilder t m, PostBuild t m) 
           => Text 
           -> Dynamic t Text 
           -> m a 
           -> m a

todoItem :: MonadWidget t m 
         => Text 
         -> m (Event t ())
todoItem placeholder =
  el      "div"             $  do

    el         "div"              $
      text placeholder

    eRemove <- button "Remove"




    pure eRemove

todoItem :: MonadWidget t m 
         => Text 
         -> m (Event t ())
todoItem placeholder =
  elClass "div"             $  do

    el         "div"              $
      text placeholder

    eRemove <- button "Remove"




    pure eRemove

todoItem :: MonadWidget t m 
         => Text 
         -> m (Event t ())
todoItem placeholder =
  elClass "div" "todo-item" $  do

    el         "div"              $
      text placeholder

    eRemove <- button "Remove"




    pure eRemove

todoItem :: MonadWidget t m 
         => Text 
         -> m (Event t ())
todoItem placeholder =
  elClass "div" "todo-item" $  do

    el         "div"              $
      text placeholder

    eRemove <- button "Remove"

    dRemoveClass <- holdDyn "" $
      "removed" <$ eRemove

    pure eRemove

todoItem :: MonadWidget t m 
         => Text 
         -> m (Event t ())
todoItem placeholder =
  elClass "div" "todo-item" $ mdo

    el         "div"              $
      text placeholder

    eRemove <- button "Remove"

    dRemoveClass <- holdDyn "" $
      "removed" <$ eRemove

    pure eRemove

todoItem :: MonadWidget t m 
         => Text 
         -> m (Event t ())
todoItem placeholder =
  elClass "div" "todo-item" $ mdo

    elDynClass "div" dRemoveClass $
      text placeholder

    eRemove <- button "Remove"

    dRemoveClass <- holdDyn "" $
      "removed" <$ eRemove

    pure eRemove

todoItem :: MonadWidget t m 
         => Text 
         -> m (Event t ())
todoItem placeholder =
  elClass "div" "todo-item" $ mdo

    elDynClass "div" dRemoveClass $
      text placeholder

    eRemove <- button "Remove"

    dRemoveClass <- holdDyn "" $
      "removed" <$ eRemove

    pure eRemove

data CheckboxConfig t = 
  CheckboxConfig { 
      _checkboxConfig_setValue   :: Event   t Bool
    , _checkboxConfig_attributes :: Dynamic t (Map Text Text)
    }
instance Reflex t => Default (CheckboxConfig t) where ...

checkbox :: (...) 
         => Bool 
         -> CheckboxConfig t 
         -> m (Checkbox t)

data Checkbox t = 
  Checkbox { 
     _checkbox_value  :: Dynamic t Bool
   , _checkbox_change :: Event   t Bool
   }

data TodoItemConfig =
  TodoItemConfig {
    _todoItemConfig_dText :: Dynamic t Text
  }

makeLenses ''TodoItemConfig

data TodoItem t =
  TodoItem {
    _todoItem_dComplete :: Dynamic t Bool
  , _todoItem_eRemove   :: Event   t ()
  }

makeLenses ''TodoItem

todoItem :: MonadWidget t m 
         => TodoItemConfig 
         -> m (TodoItem t)
todoItem (TodoItemConfig dText) =
  elClass "div" "todo-item" $ mdo
  
  
  

    elDynClass "div" dRemoveClass $
      dynText dText

    eRemove <- button "Remove"
    dRemoveClass <- holdDyn "" $ 
      "removed" <$ eRemove

    pure $ 
      TodoItem           eRemove

todoItem :: MonadWidget t m 
         => TodoItemConfig 
         -> m (TodoItem t)
todoItem (TodoItemConfig dText) =
  elClass "div" "todo-item" $ mdo
    cb <- checkbox False def
  
  

    elDynClass "div" dRemoveClass $
      dynText dText

    eRemove <- button "Remove"
    dRemoveClass <- holdDyn "" $ 
      "removed" <$ eRemove

    pure $ 
      TodoItem           eRemove

todoItem :: MonadWidget t m 
         => TodoItemConfig 
         -> m (TodoItem t)
todoItem (TodoItemConfig dText) =
  elClass "div" "todo-item" $ mdo
    cb <- checkbox False def
    let
      dComplete = cb ^. checkbox_value

    elDynClass "div" dRemoveClass $
      dynText dText

    eRemove <- button "Remove"
    dRemoveClass <- holdDyn "" $ 
      "removed" <$ eRemove

    pure $ 
      TodoItem           eRemove

todoItem :: MonadWidget t m 
         => TodoItemConfig 
         -> m (TodoItem t)
todoItem (TodoItemConfig dText) =
  elClass "div" "todo-item" $ mdo
    cb <- checkbox False def
    let
      dComplete = cb ^. checkbox_value

    elDynClass "div" dRemoveClass $
      dynText dText

    eRemove <- button "Remove"
    dRemoveClass <- holdDyn "" $ 
      "removed" <$ eRemove

    pure $ 
      TodoItem dComplete eRemove

todoItem :: MonadWidget t m 
         => TodoItemConfig 
         -> m (TodoItem t)
todoItem (TodoItemConfig dText) =
  elClass "div" "todo-item" $ mdo
    cb <- checkbox False def
    let
      dComplete = cb ^. checkbox_value

    elDynClass "div" dRemoveClass $
      dynText dText

    eRemove <- button "Remove"
    dRemoveClass <- holdDyn "" $ 
      "removed" <$ eRemove

    pure $ 
      TodoItem dComplete eRemove

  ...
    let
      dComplete = cb ^. checkbox_value






    elDynClass "div"                    dRemoveClass  $ 
      dynText dText
  ...

  ...
    let
      dComplete = cb ^. checkbox_value

      mkCompleteClass False = ""
      mkCompleteClass True  = "completed "



    elDynClass "div"                    dRemoveClass  $ 
      dynText dText
  ...

  ...
    let
      dComplete = cb ^. checkbox_value

      mkCompleteClass False = ""
      mkCompleteClass True  = "completed "

      dCompleteClass = mkCompleteClass <$> dComplete

    elDynClass "div"                    dRemoveClass  $ 
      dynText dText
  ...

  ...
    let
      dComplete = cb ^. checkbox_value

      mkCompleteClass False = ""
      mkCompleteClass True  = "completed "

      dCompleteClass = mkCompleteClass <$> dComplete

    elDynClass "div" (dCompleteClass <> dRemoveClass) $ 
      dynText dText
  ...

  ...
    let
      dComplete = cb ^. checkbox_value

      mkCompleteClass False = ""
      mkCompleteClass True  = "completed "

      dCompleteClass = mkCompleteClass <$> dComplete

    elDynClass "div" (dCompleteClass <> dRemoveClass) $ 
      dynText dText
  ...

data TextInputConfig t = 
  TextInputConfig { 
      _textInputConfig_inputType    :: Text
    , _textInputConfig_initialValue :: Text
    , _textInputConfig_setValue     :: Event t Text
    , _textInputConfig_attributes   :: 
        Dynamic t (Map Text Text)
    }
instance Reflex t => Default (TextInputConfig t) where ...

textInput :: (...) 
          => TextInputConfig t 
          -> m (TextInput t)

data TextInput t = 
  TextInput { 
      _textInput_value          :: Dynamic t Text
    , _textInput_input          :: Event t Text
    , _textInput_keypress       :: Event t Word
    , _textInput_keydown        :: Event t Word
    , _textInput_keyup          :: Event t Word
    , _textInput_hasFocus       :: Dynamic t Bool
    , _textInput_builderElement :: 
        InputElement EventResult GhcjsDomSpace t
    }

addItem ::
  MonadWidget t m =>
  m (Event t Text)
addItem =  do
  ti <- textInput $
    def                                                      









  

addItem ::
  MonadWidget t m =>
  m (Event t Text)
addItem =  do
  ti <- textInput $
    def & textInputConfig_attributes .~
            pure ("placeholder" =: "What shall we do today?")








  

addItem ::
  MonadWidget t m =>
  m (Event t Text)
addItem =  do
  ti <- textInput $
    def & textInputConfig_attributes .~
            pure ("placeholder" =: "What shall we do today?")



  let
    bValue = current $ ti ^. textInput_value



  

addItem ::
  MonadWidget t m =>
  m (Event t Text)
addItem =  do
  ti <- textInput $
    def & textInputConfig_attributes .~
            pure ("placeholder" =: "What shall we do today?")



  let
    bValue = current $ ti ^. textInput_value
    eAtEnter = bValue <@ getKey ti Enter


  

addItem ::
  MonadWidget t m =>
  m (Event t Text)
addItem =  do
  ti <- textInput $
    def & textInputConfig_attributes .~
            pure ("placeholder" =: "What shall we do today?")



  let
    bValue = current $ ti ^. textInput_value
    eAtEnter = bValue <@ getKey ti Enter
    eDone = ffilter (not . Text.null) eAtEnter

  

addItem ::
  MonadWidget t m =>
  m (Event t Text)
addItem =  do
  ti <- textInput $
    def & textInputConfig_attributes .~
            pure ("placeholder" =: "What shall we do today?")



  let
    bValue = current $ ti ^. textInput_value
    eAtEnter = bValue <@ getKey ti Enter
    eDone = ffilter (not . Text.null) eAtEnter

  pure eDone

addItem ::
  MonadWidget t m =>
  m (Event t Text)
addItem =  do
  ti <- textInput $
    def & textInputConfig_attributes .~
            pure ("placeholder" =: "What shall we do today?")
        & textInputConfig_setValue .~
            ("" <$ eDone)

  let
    bValue = current $ ti ^. textInput_value
    eAtEnter = bValue <@ getKey ti Enter
    eDone = ffilter (not . Text.null) eAtEnter

  pure eDone

addItem ::
  MonadWidget t m =>
  m (Event t Text)
addItem = mdo
  ti <- textInput $
    def & textInputConfig_attributes .~
            pure ("placeholder" =: "What shall we do today?")
        & textInputConfig_setValue .~
            ("" <$ eDone)

  let
    bValue = current $ ti ^. textInput_value
    eAtEnter = bValue <@ getKey ti Enter
    eDone = ffilter (not . Text.null) eAtEnter

  pure eDone

addItem ::
  MonadWidget t m =>
  m (Event t Text)
addItem = mdo
  ti <- textInput $
    def & textInputConfig_attributes .~
            pure ("placeholder" =: "What shall we do today?")
        & textInputConfig_setValue .~
            ("" <$ eDone)

  let
    bValue = current $ ti ^. textInput_value
    eAtEnter = bValue <@ getKey ti Enter
    eDone = ffilter (not . Text.null) eAtEnter

  pure eDone

Switching

switchPromptly :: (Reflex t, MonadHold t m) 
               => Event a 
               -> Event (Event a) 
               -> m (Event a)

switchColour :: (Reflex t, MonadHold t m) 
             => 
             

                m (Event t Colour, Event t Colour)
switchColour                          = do











  

switchColour :: (Reflex t, MonadHold t m) 
             => Event t ()
             

             -> m (Event t Colour, Event t Colour)
switchColour                          = do











  

switchColour :: (Reflex t, MonadHold t m) 
             => Event t ()
             

             -> m (Event t Colour, Event t Colour)
switchColour eSwitch1                 = do











  

switchColour :: (Reflex t, MonadHold t m) 
             => Event t ()
             -> Event t ()

             -> m (Event t Colour, Event t Colour)
switchColour eSwitch1                 = do











  

switchColour :: (Reflex t, MonadHold t m) 
             => Event t ()
             -> Event t ()

             -> m (Event t Colour, Event t Colour)
switchColour eSwitch1 eSwitch2        = do











  

switchColour :: (Reflex t, MonadHold t m) 
             => Event t ()
             -> Event t ()
             -> Event t Colour
             -> m (Event t Colour, Event t Colour)
switchColour eSwitch1 eSwitch2        = do











  

switchColour :: (Reflex t, MonadHold t m) 
             => Event t ()
             -> Event t ()
             -> Event t Colour
             -> m (Event t Colour, Event t Colour)
switchColour eSwitch1 eSwitch2 eInput = do











  

switchColour :: (Reflex t, MonadHold t m) 
             => Event t ()
             -> Event t ()
             -> Event t Colour
             -> m (Event t Colour, Event t Colour)
switchColour eSwitch1 eSwitch2 eInput = do

  eOut1 <- _




  eOut2 <- _




  pure (eOut1, eOut2)

switchColour :: (Reflex t, MonadHold t m) 
             => Event t ()
             -> Event t ()
             -> Event t Colour
             -> m (Event t Colour, Event t Colour)
switchColour eSwitch1 eSwitch2 eInput = do

  eOut1 <- switchPromptly _




  eOut2 <- switchPromptly _




  pure (eOut1, eOut2)

switchColour :: (Reflex t, MonadHold t m) 
             => Event t ()
             -> Event t ()
             -> Event t Colour
             -> m (Event t Colour, Event t Colour)
switchColour eSwitch1 eSwitch2 eInput = do

  eOut1 <- switchPromptly eInput _




  eOut2 <- switchPromptly _




  pure (eOut1, eOut2)

switchColour :: (Reflex t, MonadHold t m) 
             => Event t ()
             -> Event t ()
             -> Event t Colour
             -> m (Event t Colour, Event t Colour)
switchColour eSwitch1 eSwitch2 eInput = do

  eOut1 <- switchPromptly eInput _




  eOut2 <- switchPromptly never _




  pure (eOut1, eOut2)

switchColour :: (Reflex t, MonadHold t m) 
             => Event t ()
             -> Event t ()
             -> Event t Colour
             -> m (Event t Colour, Event t Colour)
switchColour eSwitch1 eSwitch2 eInput = do

  eOut1 <- switchPromptly eInput . leftmost $ [


    ]

  eOut2 <- switchPromptly never . leftmost $ [


    ]

  pure (eOut1, eOut2)

switchColour :: (Reflex t, MonadHold t m) 
             => Event t ()
             -> Event t ()
             -> Event t Colour
             -> m (Event t Colour, Event t Colour)
switchColour eSwitch1 eSwitch2 eInput = do

  eOut1 <- switchPromptly eInput . leftmost $ [
      eInput <$ eSwitch1

    ]

  eOut2 <- switchPromptly never . leftmost $ [


    ]

  pure (eOut1, eOut2)

switchColour :: (Reflex t, MonadHold t m) 
             => Event t ()
             -> Event t ()
             -> Event t Colour
             -> m (Event t Colour, Event t Colour)
switchColour eSwitch1 eSwitch2 eInput = do

  eOut1 <- switchPromptly eInput . leftmost $ [
      eInput <$ eSwitch1
    , never  <$ eSwitch2
    ]

  eOut2 <- switchPromptly never . leftmost $ [


    ]

  pure (eOut1, eOut2)

switchColour :: (Reflex t, MonadHold t m) 
             => Event t ()
             -> Event t ()
             -> Event t Colour
             -> m (Event t Colour, Event t Colour)
switchColour eSwitch1 eSwitch2 eInput = do

  eOut1 <- switchPromptly eInput . leftmost $ [
      eInput <$ eSwitch1
    , never  <$ eSwitch2
    ]

  eOut2 <- switchPromptly never . leftmost $ [
      never  <$ eSwitch1

    ]

  pure (eOut1, eOut2)

switchColour :: (Reflex t, MonadHold t m) 
             => Event t () 
             -> Event t () 
             -> Event t Colour 
             -> m (Event t Colour, Event t Colour)
switchColour eSwitch1 eSwitch2 eInput = do

  eOut1 <- switchPromptly eInput . leftmost $ [
      eInput <$ eSwitch1
    , never  <$ eSwitch2
    ]

  eOut2 <- switchPromptly never . leftmost $ [
      never  <$ eSwitch1
    , eInput <$ eSwitch2
    ]

  pure (eOut1, eOut2)

switchPromptly :: (Reflex t, MonadHold t m) 
               => Event a 
               -> Event    (Event a) 
               -> m (Event a)

switch         :: (Reflex t, MonadHold t m) 
               => Event a 
               -> Event    (Event a) 
               -> m (Event a)

switch         ::  Reflex t
               => Event a 
               -> Event    (Event a) 
               -> m (Event a)

switch         ::  Reflex t
               => Event a 
               -> Event    (Event a) 
               ->    Event a

switch         ::  Reflex t
               => 
                  Event    (Event a) 
               ->    Event a

switch         ::  Reflex t
               => 
                  Behavior (Event a)
               ->    Event a

switchColour :: (Reflex t, MonadHold t m) 
             => Event t () 
             -> Event t () 
             -> Event t Colour 
             -> m (Event t Colour, Event t Colour)
switchColour eSwitch1 eSwitch2 eInput = do

  eOut1 <- switchPromptly eInput . leftmost $ [
      eInput <$ eSwitch1
    , never  <$ eSwitch2
    ]

  eOut2 <- switchPromptly never . leftmost $ [
      never  <$ eSwitch1
    , eInput <$ eSwitch2
    ]

  pure (       eOut1,        eOut2)

switchColour :: (Reflex t, MonadHold t m) 
             => Event t () 
             -> Event t () 
             -> Event t Colour 
             -> m (Event t Colour, Event t Colour)
switchColour eSwitch1 eSwitch2 eInput = do

  bOut1 <- hold           eInput . leftmost $ [
      eInput <$ eSwitch1
    , never  <$ eSwitch2
    ]

  eOut2 <- switchPromptly never . leftmost $ [
      never  <$ eSwitch1
    , eInput <$ eSwitch2
    ]

  pure (       eOut1,        eOut2)

switchColour :: (Reflex t, MonadHold t m) 
             => Event t () 
             -> Event t () 
             -> Event t Colour 
             -> m (Event t Colour, Event t Colour)
switchColour eSwitch1 eSwitch2 eInput = do

  bOut1 <- hold           eInput . leftmost $ [
      eInput <$ eSwitch1
    , never  <$ eSwitch2
    ]

  bOut2 <- hold           never . leftmost $ [
      never  <$ eSwitch1
    , eInput <$ eSwitch2
    ]

  pure (       eOut1,        eOut2)

switchColour :: (Reflex t, MonadHold t m) 
             => Event t () 
             -> Event t () 
             -> Event t Colour 
             -> m (Event t Colour, Event t Colour)
switchColour eSwitch1 eSwitch2 eInput = do

  bOut1 <- hold           eInput . leftmost $ [
      eInput <$ eSwitch1
    , never  <$ eSwitch2
    ]

  bOut2 <- hold           never . leftmost $ [
      never  <$ eSwitch1
    , eInput <$ eSwitch2
    ]

  pure (switch eOut1, switch eOut2)

widget1 :: MonadWidget t m 
   => m (Event t Text)
widget1 = do

  
widget2 :: MonadWidget t m 
   => m (Event t Text)
widget2 = do

  

widget1 :: MonadWidget t m 
   => m (Event t Text)
widget1 = do
  eClick <- button "OK"
  pure $ "OK" <$ eClick
widget2 :: MonadWidget t m 
   => m (Event t Text)
widget2 = do

  

widget1 :: MonadWidget t m 
   => m (Event t Text)
widget1 = do
  eClick <- button "OK"
  pure $ "OK" <$ eClick
widget2 :: MonadWidget t m 
   => m (Event t Text)
widget2 = do
  ti <- textInput def
  pure $ ti ^. textInput_input

  eSwitch <- button "Switch"


















  

  eSwitch <- button "Switch"

  dCount <- count eSwitch
















  

  eSwitch <- button "Switch"

  dCount <- count eSwitch
  let
    dEven = fmap even dCount
    dOdd  = fmap odd  dCount













  

  eSwitch <- button "Switch"

  dCount <- count eSwitch
  let
    dEven = fmap even dCount
    dOdd  = fmap odd  dCount

  let
    mkHidden False = "hide"
    mkHidden True  = ""









  

  eSwitch <- button "Switch"

  dCount <- count eSwitch
  let
    dEven = fmap even dCount
    dOdd  = fmap odd  dCount

  let
    mkHidden False = "hide"
    mkHidden True  = ""

  eText1 <- elDynClass "div" (mkHidden <$> dEven) widget1







  

  eSwitch <- button "Switch"

  dCount <- count eSwitch
  let
    dEven = fmap even dCount
    dOdd  = fmap odd  dCount

  let
    mkHidden False = "hide"
    mkHidden True  = ""

  eText1 <- elDynClass "div" (mkHidden <$> dEven) widget1
  eText2 <- elDynClass "div" (mkHidden <$> dOdd)  widget2






  

  eSwitch <- button "Switch"

  dCount <- count eSwitch
  let
    dEven = fmap even dCount
    dOdd  = fmap odd  dCount

  let
    mkHidden False = "hide"
    mkHidden True  = ""

  eText1 <- elDynClass "div" (mkHidden <$> dEven) widget1
  eText2 <- elDynClass "div" (mkHidden <$> dOdd)  widget2

  let
    eText = leftmost [eText1, eText2]


  
  

  eSwitch <- button "Switch"

  dCount <- count eSwitch
  let
    dEven = fmap even dCount
    dOdd  = fmap odd  dCount

  let
    mkHidden False = "hide"
    mkHidden True  = ""

  eText1 <- elDynClass "div" (mkHidden <$> dEven) widget1
  eText2 <- elDynClass "div" (mkHidden <$> dOdd)  widget2

  let
    eText = leftmost [eText1, eText2]

  dText <- holdDyn "" eText

  

  eSwitch <- button "Switch"

  dCount <- count eSwitch
  let
    dEven = fmap even dCount
    dOdd  = fmap odd  dCount

  let
    mkHidden False = "hide"
    mkHidden True  = ""

  eText1 <- elDynClass "div" (mkHidden <$> dEven) widget1
  eText2 <- elDynClass "div" (mkHidden <$> dOdd)  widget2

  let
    eText = leftmost [eText1, eText2]

  dText <- holdDyn "" eText
  el "div"$
    dynText dText

widgetHold :: (MonadAdjust t m, MonadHold t m) 
           => m a 
           -> Event t (m a) 
           -> m (Dynamic t a)

  eSwitch <- button "Switch"

  dCount <- count eSwitch
  let
    dEven = fmap    even             dCount
    dOdd  = fmap    odd              dCount

  let
    mkHidden False = "hide"
    mkHidden True  = ""

  eText1 <- elDynClass "div" (mkHidden <$> dEven) widget1
  eText2 <- elDynClass "div" (mkHidden <$> dOdd)  widget2


  let
    eText = leftmost [eText1, eText2]

  dText <- holdDyn "" eText
  el "div"$ dynText dText

  eSwitch <- button "Switch"

  dCount <- count eSwitch
  let
    eEven = ffilter even . updated $ dCount
    dOdd  = fmap    odd              dCount

  let
    mkHidden False = "hide"
    mkHidden True  = ""

  eText1 <- elDynClass "div" (mkHidden <$> dEven) widget1
  eText2 <- elDynClass "div" (mkHidden <$> dOdd)  widget2


  let
    eText = leftmost [eText1, eText2]

  dText <- holdDyn "" eText
  el "div"$ dynText dText

  eSwitch <- button "Switch"

  dCount <- count eSwitch
  let
    eEven = ffilter even . updated $ dCount
    eOdd  = ffilter odd  . updated $ dCount

  let
    mkHidden False = "hide"
    mkHidden True  = ""

  eText1 <- elDynClass "div" (mkHidden <$> dEven) widget1
  eText2 <- elDynClass "div" (mkHidden <$> dOdd)  widget2


  let
    eText = leftmost [eText1, eText2]

  dText <- holdDyn "" eText
  el "div"$ dynText dText

  eSwitch <- button "Switch"

  dCount <- count eSwitch
  let
    eEven = ffilter even . updated $ dCount
    eOdd  = ffilter odd  . updated $ dCount





  eText1 <- elDynClass "div" (mkHidden <$> dEven) widget1
  eText2 <- elDynClass "div" (mkHidden <$> dOdd)  widget2


  let
    eText = leftmost [eText1, eText2]

  dText <- holdDyn "" eText
  el "div"$ dynText dText

  eSwitch <- button "Switch"

  dCount <- count eSwitch
  let
    eEven = ffilter even . updated $ dCount
    eOdd  = ffilter odd  . updated $ dCount





      widget1 <$ eEven
  eText2 <- elDynClass "div" (mkHidden <$> dOdd)  widget2


  let
    eText = leftmost [eText1, eText2]

  dText <- holdDyn "" eText
  el "div"$ dynText dText

  eSwitch <- button "Switch"

  dCount <- count eSwitch
  let
    eEven = ffilter even . updated $ dCount
    eOdd  = ffilter odd  . updated $ dCount





      widget1 <$ eEven
    , widget2 <$ eOdd


  let
    eText = leftmost [eText1, eText2]

  dText <- holdDyn "" eText
  el "div"$ dynText dText

  eSwitch <- button "Switch"

  dCount <- count eSwitch
  let
    eEven = ffilter even . updated $ dCount
    eOdd  = ffilter odd  . updated $ dCount




                                 leftmost $ [
      widget1 <$ eEven
    , widget2 <$ eOdd
    ]

  let
    eText = leftmost [eText1, eText2]

  dText <- holdDyn "" eText
  el "div"$ dynText dText

  eSwitch <- button "Switch"

  dCount <- count eSwitch
  let
    eEven = ffilter even . updated $ dCount
    eOdd  = ffilter odd  . updated $ dCount




  deText <- widgetHold widget1 . leftmost $ [
      widget1 <$ eEven
    , widget2 <$ eOdd
    ]

  let
    eText = leftmost [eText1, eText2]

  dText <- holdDyn "" eText
  el "div"$ dynText dText

  eSwitch <- button "Switch"

  dCount <- count eSwitch
  let
    eEven = ffilter even . updated $ dCount
    eOdd  = ffilter odd  . updated $ dCount




  deText <- widgetHold widget1 . leftmost $ [
      widget1 <$ eEven
    , widget2 <$ eOdd
    ]

  let
    eText = switch . current $ deText

  dText <- holdDyn "" eText
  el "div"$ dynText dText

dyn :: (MonadAdjust t m, PostBuild t m) 
    => Dynamic t (m a) 
    -> m (Event t a)

  eSwitch <- button "Switch"

  dCount <- count eSwitch
  let
    eEven = ffilter even . updated $ dCount
    eOdd  = ffilter odd  . updated $ dCount

  deText  <- widgetHold widget1 . leftmost $ [
      widget1 <$ eEven
    , widget2 <$ eOdd
    ]

  let
    eText = switch . current $ deText

  dText <- holdDyn "" eText
  el "div"$ dynText dText

  eSwitch <- button "Switch"

  dCount <- count eSwitch
  let
    eEven = ffilter even . updated $ dCount
    eOdd  = ffilter odd  . updated $ dCount

  deText  <- holdDyn widget1    . leftmost $ [
      widget1 <$ eEven
    , widget2 <$ eOdd
    ]

  let
    eText = switch . current $ deText

  dText <- holdDyn "" eText
  el "div"$ dynText dText

  eSwitch <- button "Switch"

  dCount <- count eSwitch
  let
    eEven = ffilter even . updated $ dCount
    eOdd  = ffilter odd  . updated $ dCount

  dWidget <- holdDyn widget1    . leftmost $ [
      widget1 <$ eEven
    , widget2 <$ eOdd
    ]

  let
    eText = switch . current $ deText

  dText <- holdDyn "" eText
  el "div"$ dynText dText

  eSwitch <- button "Switch"

  dCount <- count eSwitch
  let
    eEven = ffilter even . updated $ dCount
    eOdd  = ffilter odd  . updated $ dCount

  dWidget <- holdDyn widget1    . leftmost $ [
      widget1 <$ eEven
    , widget2 <$ eOdd
    ]




  dText <- holdDyn "" eText
  el "div"$ dynText dText

  eSwitch <- button "Switch"

  dCount <- count eSwitch
  let
    eEven = ffilter even . updated $ dCount
    eOdd  = ffilter odd  . updated $ dCount

  dWidget <- holdDyn widget1 .    leftmost $ [
      widget1 <$ eEven
    , widget2 <$ eOdd
    ]

  eeText <- dyn dWidget


  dText <- holdDyn "" eText
  el "div"$ dynText dText

  eSwitch <- button "Switch"

  dCount <- count eSwitch
  let
    eEven = ffilter even . updated $ dCount
    eOdd  = ffilter odd  . updated $ dCount

  dWidget <- holdDyn widget1 .    leftmost $ [
      widget1 <$ eEven
    , widget2 <$ eOdd
    ]

  eeText <- dyn dWidget
  eText  <- switchPromptly never eeText

  dText <- holdDyn "" eText
  el "div"$ dynText dText

newtype Workflow t m a = Workflow { 
    unWorkflow :: m (a, Event t (Workflow t m a))
  }
workflow :: (DomBuilder t m, MonadFix m, MonadHold t m) 
         => Workflow t m a 
         -> m (Dynamic t a)

  eSwitch <- button "Switch"












  deText <- _

  let eText = switch . current $ deText

  dText <- holdDyn "" eText
  el "div"$ dynText dText

  eSwitch <- button "Switch"

  let
    workflow1 :: Workflow t m (Event t Text)
    worfklow1 = Workflow $ do
      eText1 <- widget1
      pure (eText1, workflow2 <$ eSwitch)






  deText <- _

  let eText = switch . current $ deText

  dText <- holdDyn "" eText
  el "div"$ dynText dText

  eSwitch <- button "Switch"

  let
    workflow1 :: Workflow t m (Event t Text)
    worfklow1 = Workflow $ do
      eText1 <- widget1
      pure (eText1, workflow2 <$ eSwitch)

    workflow2 :: Workflow t m (Event t Text)
    workflow2 = Workflow $ do
      eText2 <- widget2
      pure (eText2, workflow1 <$ eSwitch)

  deText <- _

  let eText = switch . current $ deText

  dText <- holdDyn "" eText
  el "div"$ dynText dText

  eSwitch <- button "Switch"

  let
    workflow1 :: Workflow t m (Event t Text)
    worfklow1 = Workflow $ do
      eText1 <- widget1
      pure (eText1, workflow2 <$ eSwitch)

    workflow2 :: Workflow t m (Event t Text)
    workflow2 = Workflow $ do
      eText2 <- widget2
      pure (eText2, workflow1 <$ eSwitch)

  deText <- workflow workflow1

  let eText = switch . current $ deText

  dText <- holdDyn "" eText
  el "div"$ dynText dText

Collections

addItemWidget :: MonadWidget t m 
              => m (Event t Text)

  ...

  -- eAdd     :: Event t Text
  eAdd <- addItemWidget








  ...

  ...

  -- eAdd     :: Event t Text
  eAdd <- addItemWidget

  -- dNextKey :: Dynamic t Int
  dNextKey <- count eAdd





  ...

  ...

  -- eAdd     :: Event t Text
  eAdd <- addItemWidget

  -- dNextKey :: Dynamic t Int
  dNextKey <- count eAdd

  -- dMap     :: Dynamic t (Map Int Text)
  dMap <- foldDyn ($) Map.empty $
      Map.insert <$> current dNextKey <@> eAdd

  ...

todoItem :: MonadWidget t m 
            -- The value of the text for the item
         => Dynamic t Text
            -- Fires when item should be removed
         -> m (Event t ())

dMap 
  :: Dynamic t (Map Int Text)









  

dMap 
  :: Dynamic t (Map Int Text)

todoItem
  :: MonadWidget t m
  => Dynamic t Text
  -> m (Event t ())




    

dMap 
  :: Dynamic t (Map Int Text)

todoItem 
  :: MonadWidget t m
  => Dynamic t Text
  -> m (Event t ())

list 
  ::         Dynamic t (Map k v     )
  ->   (Dynamic t v -> m a   ) 
  -> m (Dynamic t (Map k a         ))

dMap 
  :: Dynamic t (Map Int Text)

todoItem
  :: MonadWidget t m
  => Dynamic t Text
  -> m (Event t ())

list dMap 
  ::
       (Dynamic t Text -> m a) 
  -> m (Dynamic t (Map Int a       ))

dMap 
  :: Dynamic t (Map Int Text)

todoItem
  :: MonadWidget t m
  => Dynamic t Text
  -> m (Event t ())

list dMap todoItem 
  ::

     m (Dynamic t (Map Int (Event t ())))

  -- Dynamic t (Map Int (Event t ()))
  dmItems <-           list dMap $ \dv -> 
                         todoItem dv

  -- Dynamic t (Map Int (Event t ()))
  dmItems <- el "ul" . list dMap $ \dv -> 
               el "li" . todoItem $ dv

  let
    eRemoves =
    







      -- Dynamic t (Map Int (Event t ()))
      dmItems

  let
    eRemoves =
    





      -- Dynamic t (Event t (Map Int ()))
      fmap mergeMap $
      -- Dynamic t (Map Int (Event t ()))
      dmItems

  let
    eRemoves =
    



      -- Behavior t (Event t (Map Int ()))
      current .
      -- Dynamic t (Event t (Map Int ()))
      fmap mergeMap $
      -- Dynamic t (Map Int (Event t ()))
      dmItems

  let
    eRemoves =
    

      -- Event t (Map Int ())
      switch .
      -- Behavior t (Event t (Map Int ()))
      current .
      -- Dynamic t (Event t (Map Int ()))
      fmap mergeMap $
      -- Dynamic t (Map Int (Event t ()))
      dmItems

  let
    eRemoves =
      -- Event t [Int]
      fmap Map.keys .
      -- Event t (Map Int ())
      switch .
      -- Behavior t (Event t (Map Int ()))
      current .
      -- Dynamic t (Event t (Map Int ()))
      fmap mergeMap $
      -- Dynamic t (Map Int (Event t ()))
      dmItems

  dmText <- foldDyn ($) Map.empty                 $
      Map.insert <$> current dNextKey <@> eAdd



  dmItems <- el "ul" . list dMap $ \dv -> 
    el "li"  todoItem $ dv








  

  dmText <- foldDyn ($) Map.empty . mergeWith (.) $ [
      Map.insert <$> current dNextKey <@> eAdd

    ]

  dmItems <- el "ul" . list dMap $ \dv -> 
    el "li"  todoItem $ dv








  

  dmText <- foldDyn ($) Map.empty . mergeWith (.) $ [
      Map.insert <$> current dNextKey <@> eAdd

    ]

  dmItems <- el "ul" . list dMap $ \dv -> 
    el "li"  todoItem $ dv

  let
    -- Event t [Int]
    eRemoves =
      fmap Map.keys .
      switch .
      current .
      fmap mergeMap $
      dmItems

  dmText <- foldDyn ($) Map.empty . mergeWith (.) $ [
      Map.insert <$> current dNextKey <@> eAdd
    , flip (foldr Map.delete) <$> eRemoves
    ]

  dmItems <- el "ul" . list dMap $ \dv -> 
    el "li"  todoItem $ dv

  let
    -- Event t [Int]
    eRemoves =
      fmap Map.keys .
      switch .
      current .
      fmap mergeMap $
      dmItems

Conclusion

reflex-frp on Freenode

QuickRef.md

Real World Reflex

Part 2