I am trying to implement the dynamic wire set in netwire 5 "correctly." I read the answer to the question of wire wires , and I don’t really like how the code in the example relies on Event
, converted to behavior, to display not empty only with one execution stepWire
.
So, I want to add and remove wires in a dynamic set using Event
s, and hopefully without clicking on Unsafe.Event
or an equivalent hacker. Leave the deletion part for simplicity and just add Wire
s:
dynWireSet1 :: (Monad m, Monoid s)
=> Wire s e m (a, Event (Wire s e m a b)) [b]
Each event adds a new wire to the (initially empty) list (or other set) of wires hidden inside, and they all fire, they all receive type input a
, and their outputs are collected in a list.
The working part is relatively simple, with googleable examples, for example:
dynWireSet1 = runWires1 []
runWires1 :: (Monad m, Monoid s)
=> [Wire s e m a b]
-> Wire s e m (a, Event (Wire s e m a b)) [b]
runWires1 wires = mkGen $ \session (input, event) -> do
stepped <- mapM (\w -> stepWire w session (Right input)) wires
let (outputs, newwires) = unzip stepped
return (sequence outputs, runWires1 newwires)
The example above ignores events. I suspect that it is not possible to use the event inside the transition function except
Event
from Unsafe.Event
. It's right? I want to avoid Unsafe.Event
.
When I step back and look at the suggested ways to use events, I see a function that looks very promising:
krSwitch :: Monad m
=> Wire s e m a b
-> Wire s e m (a, Event (Wire s e m a b -> Wire s e m a b)) b
Now, if I start with simplified runWires:
runWires2 :: (Monad m, Monoid s)
=> [Wire s e m a b]
-> Wire s e m a [b]
runWires2 wires = mkGen $ \session input -> do
stepped <- mapM (\w -> stepWire w session (Right input)) wires
let (outputs, newwires) = unzip stepped
return (sequence outputs, runWires2 newwires)
and make dynWireSet krSwitch:
dynWireSet2 :: (Monad m, Monoid s)
=> Wire s e m (a, Event (Wire s e m a b)) [b]
dynWireSet2 = krSwitch (runWires2 []) . second (mkSF_ (fmap addWire))
addWire :: Wire s e m a b -> Wire s e m a [b] -> Wire s e m a [b]
addWire = undefined
! , fmap
a (:)
runWires2
, newwires
, ! , . , fmap
WGen
fmaps
, . .
, . data Wire
, WCarry g st
, .
((a, c) -> m (b, c))
, , Wire :
mkCarry :: Monad m => ((a, c) -> m (b, c)) -> c -> Wire s e m a b
mkCarry transfun state = mkGenN $ \input -> do
(output, newstate) <- transfun (input, state)
return (Right output, mkCarry transfun newstate)
WCarry
WGen
. runWires
mkCarry
.
fmap :
fmap f (WCarry g st) = WCarry g (fmap f st)
It will change the state object "hidden inside", and we can use the function krSwitch
for this type Wire
s to adjust the internal state without losing the previous value.
It makes sense? If what I'm trying to do is possibly in a simpler way, I advise! If what I'm talking about makes sense, how can I do this? Is it possible to locally expand the definition data Wire
using WCarry and expand the addition of interesting class instances with the corresponding definitions? Any other tips?Thanks.