Deku logo

Functional reactive programming

Event miscellany

Because who likes to lift2 over append when you can just append?

One of the annoying bits of working with any functorial type is that, for basic operations, you constantly have to map and lift2. This gets un-fun after a while, so it's a common convention to add sensible instances of typeclasses related to the type a in f a provided that there's an unambiguous interpretation of what they mean. Thankfully, in the case of Event, this is possible for many core typeclasses.


Semigroups

Events can be considered Semigroups if the underlying type is a Semigroup. This follows the classic pattern of equating <> with <*>.

Events as semigroups

The example below shows how two events can be appended together to control classes in the DOM.

View on GithubVITE_START=EventsAsSemigroups pnpm example
module Examples.EventsAsSemigroups where

import Prelude
import Deku.Toplevel (runInBody)

import Data.Tuple.Nested ((/\))
import Deku.DOM.Attributes as DA
import Deku.Toplevel (runInBody)

import Deku.Control (text_)
import Deku.DOM as D
import Deku.Do as Deku
import Deku.Hooks (useState')
import Deku.DOM.Listeners as DL
import Deku.Toplevel (runInBody)
import Effect (Effect)
import ExampleAssitant (ExampleSignature)
import Deku.Toplevel (runInBody)

buttonClass =
  """inline-flex items-center rounded-md
border border-transparent bg-indigo-600 px-3 py-2
text-sm font-medium leading-4 text-white shadow-sm
hover:bg-indigo-700 focus:outline-none focus:ring-2
focus:ring-indigo-500 focus:ring-offset-2 mr-6""" :: String

main :: Effect Unit
main = void $ runInBody Deku.do
  setKlass1 /\ klass1 <- useState'
  setKlass2 /\ klass2 <- useState'
  let
    button setter txt = D.button
      [ DA.klass_ buttonClass, DL.click_ \_ -> (setter txt) ]
      [ text_ txt ]
  D.div_
    [ D.div_ $
        [ button setKlass1 "text-2xl"
        , button setKlass1 "text-sm"
        , button setKlass2 "text-orange-500"
        , button setKlass2 "text-green-300"
        ]
    , D.div_
        [ D.span
            [ DA.klass_ "text-sm text-green-500"
            , DA.klass ((klass1 <#> (_ <> " ")) <> klass2)
            ]
            [ text_ "Hello!" ]
        ]
    ]
Hello!

Events aren't monoids

Alas, Event a is not a Monoid because it has no Applicative instance, so we can't do pure mempty. If you really need a Monoid out of an Event, you can always useEndo.

Previous
Filtering