[Haskell-beginners] How to structure an application?

Tilmann t_gass at gmx.de
Sun Jun 28 14:03:37 UTC 2020


Hi,

I hope to get some advice on how to structure an application. So I
acquire a handle early on that I use all over the app, but I don't want
to pass the handle itself around, but wrap the handle with "commands"
that a) make a nicer api and/or b) only allow specific usecases of the
handle. I tried and failed to use MonadReader in a straightforward way
and now I'm wondering what options there are. Looking forward to your
feedback,

Best,

Tilmann


module Main where

import           Control.Monad
import           Control.Monad.Reader
import           Graphics.UI.WX
import           System.IO


-- imagine many more commands like this one
ping :: (MonadReader Handle m, MonadIO m) => m ()
ping = do
  h <- ask
  liftIO $ hPutStrLn h "ping"


main :: IO ()
main = do
  let h = stdout -- in the real app, this handle isn't stdout of course
but opened separately
  start $ runReaderT wxApp h

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 ()





-- Alternatively
main2 :: IO ()
main2 = do
  let h = stdout
  start $ runReaderT wxApp2 (mkCommands h)

wxApp2 :: (MonadReader Commands m, MonadIO m) => m ()
wxApp2 = do
  commands <- ask
  liftIO $ do
    f <- frame [ ]
    timer f [ interval := 1000
            , on command := ping2 commands
            , enabled := True]
    return ()

data Commands = Commands {
    ping2 :: IO ()
  -- .. many more
}


mkCommands :: Handle -> Commands
mkCommands h = Commands (hPutStrLn h "ping")



More information about the Beginners mailing list