Send Beginners mailing list submissions to
        beginners@haskell.org

To subscribe or unsubscribe via the World Wide Web, visit
        http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
or, via email, send a message with subject or body 'help' to
        beginners-requ...@haskell.org

You can reach the person managing the list at
        beginners-ow...@haskell.org

When replying, please edit your Subject line so it is more specific
than "Re: Contents of Beginners digest..."


Today's Topics:

   1. Re:  How to structure an application? (Magnus Therning)
   2. Re:  How to structure an application? (Daniel Trstenjak)


----------------------------------------------------------------------

Message: 1
Date: Tue, 30 Jun 2020 23:54:13 +0200
From: Magnus Therning <mag...@therning.org>
To: beginners@haskell.org
Subject: Re: [Haskell-beginners] How to structure an application?
Message-ID: <87a70kdxtm....@therning.org>
Content-Type: text/plain; charset="utf-8"


Tilmann <t_g...@gmx.de> writes:

> 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,

Below a certain size I'd actually consider just passing the handle
around, possibly in a type holding other info that's needed "all over."

At some point that becomes unwieldy and then I'd look at things like

- monad transformers (like you have below)
- tagless final: https://serokell.io/blog/2018/12/07/tagless-final
- readerT design pattern: 
https://www.fpcomplete.com/blog/2017/06/readert-design-pattern

I'm not too experienced with them, but I'm guessing free monads/effects
would be an alternative too...

/M

--
Magnus Therning              OpenPGP: 0x927912051716CE39
email: mag...@therning.org
twitter: magthe              http://magnus.therning.org/

I am always doing that which I cannot do, in order that I may learn
how to do it.
     — Pablo Picasso
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 832 bytes
Desc: not available
URL: 
<http://mail.haskell.org/pipermail/beginners/attachments/20200630/fc1d0c2c/attachment-0001.sig>

------------------------------

Message: 2
Date: Wed, 1 Jul 2020 10:31:35 +0200
From: Daniel Trstenjak <daniel.trsten...@gmail.com>
To: The Haskell-Beginners Mailing List - Discussion of primarily
        beginner-level topics related to Haskell <beginners@haskell.org>
Subject: Re: [Haskell-beginners] How to structure an application?
Message-ID: <20200701083135.GB3366@octa>
Content-Type: text/plain; charset=iso-8859-1

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


------------------------------

Subject: Digest Footer

_______________________________________________
Beginners mailing list
Beginners@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners


------------------------------

End of Beginners Digest, Vol 145, Issue 1
*****************************************

Reply via email to