Skip to content

Instantly share code, notes, and snippets.

@jfischoff
Last active August 22, 2019 20:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jfischoff/04bd9152d6c6e5bd8080a4f0b1b619dd to your computer and use it in GitHub Desktop.
Save jfischoff/04bd9152d6c6e5bd8080a4f0b1b619dd to your computer and use it in GitHub Desktop.
type WidgetFlow t m a = Workflow t (VtyWidget t m) a
testScreen
:: (Reflex t, Show a, Show b, Monad m)
=> a
-- ^ Input
-> (a -> VtyWidget t m (Event t b))
-- ^ Screen to test
-> (b -> WidgetFlow t m ())
-- ^ Next continuation
-> WidgetFlow t m ()
testScreen theInput screenToTest next = Workflow $ do
inputScreenFinishedEvent <- makeInputScreen theInput
pure ((), ffor inputScreenFinishedEvent $ \() -> Workflow $ do
testScreenFinished <- screenToTest theInput
pure ((), ffor testScreenFinished $ \output -> Workflow $ do
outputScreenFinishedEvent <- makeOutputScreen output
pure ((), ffor outputScreenFinishedEvent $ \() -> next output)))
@samtay
Copy link

samtay commented Aug 22, 2019

testScreen theInput screenToTest next = initWf
 where
  initWf = Workflow $ do
    inputScreenFinishedEvent <- makeInputScreen theInput
    pure ((), screenToTestWf <$ inputScreenFinishedEvent)
  screenToTestWf = Workflow $ do
    testScreenFinished <- screenToTest theInput
    pure ((), nextWf <$> testScreenFinished)
  nextWf output = Workflow $ do
    outputScreenFinishedEvent <- makeOutputScreen output
    pure ((), next output <$ outputScreenFinishedEvent)

Embracing the <$ for events might make this feel a little less CPS-y

@samtay
Copy link

samtay commented Aug 22, 2019

Just realized you were talking about passing in that next arg. Maybe return the output event like:

caller = do
  outputEvent <- switch . current <$> workflow (testScreenWf theInput screenToTest)
  do next something with outputEvent

testScreenWf :: a -> (a -> VtyWidget t m (Event t b)) -> WidgetFlow t m (Event t b)
testScreenWf theInput screenToTest = initWf
 where
  initWf = Workflow $ do
    inputScreenFinishedEvent <- makeInputScreen theInput
    pure (never, screenToTestWf <$ inputScreenFinishedEvent)
  screenToTestWf = Workflow $ do
    outputEvent <- screenToTest theInput
    pure (outputEvent, never)

Hard to say without seeing more code. This kinda sequencing stuff can be awkward. I think workflow probably is the way to go, but you do need them to be "in scope" to call them from each other, AFAIK. So the testScreen will have to know about what's "coming next".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment