host :: (forall t m. TypingApp t m) -> IO ()
host myGuest =
  runSpiderHost $ do
    (e, eTriggerRef) <- newEventWithTriggerRef
    let windowHandler :: FL.Ref DoubleWindow -> FL.Event -> IO (Either UnknownEvent ())
        windowHandler window fltkEvent =
          case fltkEvent of
            Keydown -> do
              keyPressed <- FL.eventText
              eventTrigger <- liftIO (readIORef eTriggerRef)
              if (not (T.null keyPressed))
                then runSpiderHost $
                       case eventTrigger of
                          Nothing -> return ()
                          Just event ->
                            fireEvents [event :=> Identity (Prelude.head (T.unpack keyPressed))] >>
                            liftIO (return ())
                else return ()
              return (Right ())
            _ -> handleSuper window fltkEvent
    b <- runHostFrame (myGuest e)
    liftIO $ do
      w <- makeWindow windowHandler
      begin w
      makeDescription
      (buffer,o) <- makeOutput
      end w
      setResizable w (Just o)
      showWidget w
      go (do
           leftTodo <- FL.wait
           return (leftTodo > 0)
         )
         (runSpiderHost $ do
            output <- runHostFrame (sample b)
            liftIO $ do
              newOutput <- outputChanged buffer (T.pack output)
              if newOutput
                then do
                  emptyBuffer <- getText buffer >>= return . T.null
                  appendToBuffer buffer (T.pack (if emptyBuffer then output else ("\n" ++ output)))
                else return ())
  where
    go :: IO Bool -> IO ()  -> IO ()
    go predicateM action = do
      predicate <- predicateM
      if predicate
        then action >> go predicateM action
        else return ()
host :: (forall t m. TypingApp t m) -> IO ()
host myGuest =
  runSpiderHost $ do
    (e, eTriggerRef) <- newEventWithTriggerRef
    let windowHandler :: FL.Ref DoubleWindow -> FL.Event -> IO (Either UnknownEvent ())
        windowHandler window fltkEvent =
          case fltkEvent of
            Keydown -> do
              keyPressed <- FL.eventText
              eventTrigger <- liftIO (readIORef eTriggerRef)
              if (not (T.null keyPressed))
                then runSpiderHost $
                       case eventTrigger of
                          Nothing -> return ()
                          Just event ->
                            fireEvents [event :=> Identity (Prelude.head (T.unpack keyPressed))] >>
                            liftIO (return ())
                else return ()
              return (Right ())
            _ -> handleSuper window fltkEvent
    b <- runHostFrame (myGuest e)
    liftIO $ do
      w <- makeWindow windowHandler
      begin w
      makeDescription
      (buffer,o) <- makeOutput
      end w
      setResizable w (Just o)
      showWidget w
      go (do
           leftTodo <- FL.wait
           return (leftTodo > 0)
         )
         (runSpiderHost $ do
            output <- runHostFrame (sample b)
            liftIO $ do
              newOutput <- outputChanged buffer (T.pack output)
              if newOutput
                then do
                  emptyBuffer <- getText buffer >>= return . T.null
                  appendToBuffer buffer (T.pack (if emptyBuffer then output else ("\n" ++ output)))
                else return ())
  where
    go :: IO Bool -> IO ()  -> IO ()
    go predicateM action = do
      predicate <- predicateM
      if predicate
        then action >> go predicateM action
        else return ()
host myGuest =
  runSpiderHost $ do
    (e, eTriggerRef) <- newEventWithTriggerRef
    let windowHandler :: FL.Ref DoubleWindow -> FL.Event -> IO (Either UnknownEvent ())
        windowHandler window fltkEvent =
          case fltkEvent of
            Keydown -> do
              keyPressed <- FL.eventText
              eventTrigger <- liftIO (readIORef eTriggerRef)
              if (not (T.null keyPressed))
                then runSpiderHost $
                       case eventTrigger of
                          Nothing -> return ()
                          Just event ->
                            fireEvents [event :=> Identity (Prelude.head (T.unpack keyPressed))] >>
                            liftIO (return ())
                else return ()
              return (Right ())
            _ -> handleSuper window fltkEvent
    b <- runHostFrame (myGuest e)
    liftIO $ do
      w <- makeWindow windowHandler
      begin w
      makeDescription
      (buffer,o) <- makeOutput
      end w
      setResizable w (Just o)
      showWidget w
      go (do
           leftTodo <- FL.wait
           return (leftTodo > 0)
         )
         (runSpiderHost $ do
            output <- runHostFrame (sample b)
            liftIO $ do
              newOutput <- outputChanged buffer (T.pack output)
              if newOutput
                then do
                  emptyBuffer <- getText buffer >>= return . T.null
                  appendToBuffer buffer (T.pack (if emptyBuffer then output else ("\n" ++ output)))
                else return ())
  where
    go :: IO Bool -> IO ()  -> IO ()
    go predicateM action = do
      predicate <- predicateM
      if predicate
        then action >> go predicateM action
        else return ()