[Haskell-beginners] lazy mapM

Ovidiu D ovidiudeac at gmail.com
Mon Apr 1 03:38:56 CEST 2013


I'm not sure I understand what you mean by "I know you have the best
intentions in writing this, but there are pitfalls.". Anyway, here's the
code which doesn't work apparently because mapM is waiting for the whole
list before it goes further.

prompt = ">> "

commands :: [IO String]
commands = readCommand : commands
    where readCommand = putStr prompt >> getLine

display :: Show a => [ a ] -> IO ()
display = mapM_ $ putStr . show

executeCommand :: String -> String
executeCommand = printf "Command not implemented: '%s'"

processCommands :: [IO String] -> IO [ String ]
processCommands = mapM processOneCommand
    where processOneCommand cmd = cmd >>= (return . executeCommand )

main =
    hSetBuffering stdout NoBuffering
    >> processCommands commands
    >>= display

This is just for learning purposes and I'm looking for the "haskell way to
do it". My intention is to write the function processCommands such that it
takes the decision to either fetch the next command from the command list
(i.e. console) or to exit the application.

Regarding your comment "Just know that at some point you should learn to
use conduits or pipes for a much better approach to modeling things like
this.". Can you point me to some documentation?

Thanks!


On Mon, Apr 1, 2013 at 3:53 AM, David McBride <toad3k at gmail.com> wrote:

> I know you have the best intentions in writing this, but there are
> pitfalls.  Unexpected things happen when you interleave IO in this manner,
> but nonetheless, here's how you would do it.
>
> myGetLine = do
>   x <- getLine
>   if (x == "exit")
>       then return []
>       else do
>         xs <- unsafeInterleaveIO myGetLine
>         return (x:xs)
>
> main = do
>   x <- myGetLine
>   print x
>
> Just know that at some point you should learn to use conduits or pipes for
> a much better approach to modeling things like this.
>
>
>
> On Sun, Mar 31, 2013 at 7:26 PM, Ovidiu D <ovidiudeac at gmail.com> wrote:
>
>> Hi again,
>>
>> Given the following code:
>>
>> g :: IO String -> IO String
>>
>> f :: [IO String] -> IO [ String ]
>> f = mapM g
>>
>> The implementation of f is wrong because I would like to:
>> 1. Make f behave lazy
>> Its input list is made of lines read from stdin and I want it to process
>> lines one by one as they are entered by the user.
>>
>> 2. Implement  f such that it stops consuming items from the input list
>> when the input item meets some condition. For example:
>> isExit item = ("exit" == item)
>>
>> I tried to implement my own custom iteration by recursion but I got stuck
>> in the combination of IO and list monads.
>>
>> Any help is appreciated.
>>
>> Thanks!
>>
>>
>> _______________________________________________
>> Beginners mailing list
>> Beginners at haskell.org
>> http://www.haskell.org/mailman/listinfo/beginners
>>
>>
>
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://www.haskell.org/mailman/listinfo/beginners
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/beginners/attachments/20130401/c1636782/attachment.htm>


More information about the Beginners mailing list