[Haskell-beginners] How to structure an application?

Daniel Trstenjak daniel.trstenjak at gmail.com
Wed Jul 1 08:31:35 UTC 2020


Hi Tilmann,

> wxApp :: (MonadReader Handle m, MonadIO m) => m ()
> wxApp = do
>   ping -- this works, but I don't need it here..
>   liftIO $ do
>     f <- frame [ ]
>     timer f [ interval := 1000
>             -- , on command := hputStrLn h "ping" -- this is what I try
> to avoid
>             -- , on command := ping -- of course, this doesn't work, but
> it would be so nice..
>             , enabled := True]
>     return ()

I assume that WX expects an 'IO' action for the 'command', but 'ping' is
an action of the 'ReaderT' monad.

WX won't be able to execute this action, because it doesn't know
anything about the 'ReaderT' monad, so there's no 'Handle' that
it could give to the 'ping' function.

I think the most straight forward solution is to have a function 'ping':

   ping :: Handle -> IO ()
   ping h = hputStrLn h "ping"


And then a 'wxApp' like:
      
   wxApp :: (MonadReader Handle m, MonadIO m) => m ()
   wxApp = do
     handle <- ask
     liftIO $ do
       f <- frame [ ]
       timer f [ interval := 1000, on command := ping handle, enabled := True]
       return ()


So instead of having 'ping' in the 'ReaderT' monad you just give it
explicitly the data of the monad.


You could have a helper function that does this transformation:

   handlize :: (MonadReader Handle m, MonadIO m) => (Handle -> IO()) -> m (IO ())
   handlize func = do
     handle <- ask
     return $ func handle

   wxApp :: (MonadReader Handle m, MonadIO m) => m ()
   wxApp = do
     cmd <- handlize ping
     liftIO $ do
       f <- frame [ ]
       timer f [ interval := 1000, on command := cmd, enabled := True]
       return ()


Greetings,
Daniel


More information about the Beginners mailing list