How do I perform things inside a Monad?

Hello all, In the ALSA Midi package, there is an example, where he first sets up client, port, queue and stuff. All of these are IO actions, and there are a number of nested "do"s. Then in the innermost "do" he has all the pieces together and starts playing. In this case the actual "song" is coded in the innermost do. My question is: how can I inject a song from outside. Of course I could make it another parameter, which would have to travel through all the "do"s, but I already have more than enough parameters. Then I tried fmap. But the actual playing is an IO operation itself, so I cannot write a pure function and fmap it over the Monad. Any ideas? -- Martin

On Thu, Feb 07, 2013 at 11:07:57PM +0100, Martin Drautzburg wrote:
Hello all,
In the ALSA Midi package, there is an example, where he first sets up client, port, queue and stuff. All of these are IO actions, and there are a number of nested "do"s. Then in the innermost "do" he has all the pieces together and starts playing. In this case the actual "song" is coded in the innermost do.
My question is: how can I inject a song from outside. Of course I could make it another parameter, which would have to travel through all the "do"s, but I already have more than enough parameters.
Just make it a parameter. If it is in scope, you can use it in the innermost 'do'. I'm not sure what you mean by "travel through all the "do"s". You don't have to do anything special to make this happen. Like so: foo bar baz = do withFoo $ \foo -> do blub withOtherThing $ \thing -> do blah something bar baz Notice how 'bar' and 'baz' are automatically in scope throughout the whole thing, even the innermost do. -Brent

On Thursday, 7. February 2013 23:25:32 Brent Yorgey wrote:
On Thu, Feb 07, 2013 at 11:07:57PM +0100, Martin Drautzburg wrote:
Hello all,
In the ALSA Midi package, there is an example, where he first sets up client, port, queue and stuff. All of these are IO actions, and there are a number of nested "do"s. Then in the innermost "do" he has all the pieces together and starts playing. In this case the actual "song" is coded in the innermost do.
My question is: how can I inject a song from outside. Of course I could make it another parameter, which would have to travel through all the "do"s, but I already have more than enough parameters.
Just make it a parameter. If it is in scope, you can use it in the innermost 'do'. I'm not sure what you mean by "travel through all the "do"s". You don't have to do anything special to make this happen. Like so:
foo bar baz = do withFoo $ \foo -> do blub withOtherThing $ \thing -> do blah something bar baz
Notice how 'bar' and 'baz' are automatically in scope throughout the whole thing, even the innermost do.
The original code was written exactly in this style. Is this "$ \foo ->do" cascade some kind of idiom? The thing is, I tried to split this monster up into several functions. For this, my functions got quite a number of parameters. Passing bar baz to the toplevel function would add even more parameters. I understand why your suggestion works without "tramp" parameters. But somehow I don't like "$ \foo ->do" cascades. It looks ugly and I do not fully understand the pattern and when and why it is needed. If there are situations which require three nested "do"s, then there might be situations which require 1000 nested "do"s. It just won't scale. -- Martin

Hi Martin, On Fri, Feb 08, 2013 at 07:18:38AM +0100, Martin Drautzburg wrote:
The thing is, I tried to split this monster up into several functions. For this, my functions got quite a number of parameters. Passing bar baz to the toplevel function would add even more parameters.
You might use the where clause: foo bar baz = withFoo doFoo where doFoo foo = do blub withOtherThing doOtherThing doOtherThing thing = do blah something bar baz Greetings, Daniel
participants (3)
-
Brent Yorgey
-
Daniel Trstenjak
-
Martin Drautzburg