Skip to content

Instantly share code, notes, and snippets.

@bontaq
Last active July 30, 2022 17:54
Show Gist options
  • Save bontaq/803cea883a62e95a25d39380e9ffe18e to your computer and use it in GitHub Desktop.
Save bontaq/803cea883a62e95a25d39380e9ffe18e to your computer and use it in GitHub Desktop.
{-
This is for a sort of web framework I've been working on.
Handlers can send events to themselves, or to a parent handler.
Senders (triggered by events in the HTML) can only send events to the
handler above them in the graph.
There will be few handlers / senders, and a lot of Html. Having the
parentEvent on Senders and Html doesn't fit the model, since it's
not needed. Is there a better way to model this that would remove
parentEvent, but still keep track of it? New Handlers can be anywhere
in the tree and need to know what events it can send to the parent.
If there was some way for the Handler to "know" that the "event" type
of the Sender / Html it's embedded in was its "parentEvent" type, that'd
be pretty cool but might not be possible?
I've been wondering if this could be solved with implicit params or
something monadic, but I'm not sure.
-}
data Event a b = Parent a | Self b
data Graph parentEvent event where
Sender
:: event
-> [Graph parentEvent event]
-- ^ children
-> Graph parentEvent event
Handler ::
{ handler :: newEvent -> [Event parentEvent newEvent]
-- ^ receives the sender event and generates new events
, children :: [Graph newEvent any]
}
-> Graph parentEvent newEvent
Html
:: String
-> [Graph parentEvent event]
-- ^ children
-> Graph parentEvent event
data Vertical = North | South
data Horizontal = East | West
-- here you can see where having the parentEvent type makes less sense
westSender :: Graph parentEvent Horizontal
westSender = Sender West []
child :: Graph Vertical Horizontal
child = Handler (\event -> [ Parent North, Self East ]) [ westSender, eastSender ]
parent :: [Graph Vertical any] -> Graph () Vertical
parent = Handler (\event -> [ Self North ])
graph :: Graph () Vertical
graph = parent [ child ]
-- I see I can do something like this:
type Graph' event = forall parentEvent. Graph parentEvent event
-- to hide having to type out the parentEvent, but it's still not
-- exactly matching with how it really works
eastSender :: Graph' Horizontal
eastSender = Sender East []
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment