Send Beginners mailing list submissions to
        [email protected]

To subscribe or unsubscribe via the World Wide Web, visit
        http://www.haskell.org/mailman/listinfo/beginners
or, via email, send a message with subject or body 'help' to
        [email protected]

You can reach the person managing the list at
        [email protected]

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


Today's Topics:

   1. Re:  lazy mapM (David McBride)
   2. Re:  [IO String] to IO [String] (Lyndon Maydwell)
   3. Re:  [IO String] to IO [String] (Ovidiu D)


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

Message: 1
Date: Sun, 31 Mar 2013 22:51:27 -0400
From: David McBride <[email protected]>
Subject: Re: [Haskell-beginners] lazy mapM
To: The Haskell-Beginners Mailing List - Discussion of primarily
        beginner-level topics related to Haskell <[email protected]>
Message-ID:
        <can+tr40ziofaab1h2fqbhftwzeokcudxtyzhsse_stb7uce...@mail.gmail.com>
Content-Type: text/plain; charset="iso-8859-1"

I'm sorry I jacked up the code editing my email inline, the pipes section
below main should look like this:

commandProducer :: Producer String IO ()
commandProducer = do
  x <- lift getLine
  if x == "exit"
    then return ()
    else P.yield x >> commandProducer

displayConsumer :: PrintfArg a => Consumer a IO ()
displayConsumer = forever $ P.await >>= lift . printf "Command not
implemented (pipes): '%s'\n"



On Sun, Mar 31, 2013 at 10:49 PM, David McBride <[email protected]> wrote:

> Doing it the way you are trying to do it breaks the IO abstraction.  In
> order to do it you'd have to use unsafe functions.  Unsafe functions are
> bad.  I'm not going to explain why but they tend to bite you as your
> program gets more complex and weirdness starts to occur, like threads
> ceasing operation while awaiting input is something that bit me when I went
> down that route.  So let me explain how I would do it using both pipes and
> conduits as examples:
>
> import Data.Conduit as C hiding ((>+>), runPipe)
> import System.IO
> import Control.Monad.Trans
> import Text.Printf.Mauke
>
> import Control.Pipe as P
> import Control.Monad (forever)
>
> -- Source runs in the IO monad and produces Strings
> commandSource :: Source IO String
> commandSource = do
>   command <- liftIO getLine
>   if command == "exit"
>     then return ()
>     else do
>       C.yield command
>       commandSource -- loop to fetching new values to send down the pipe
>
> -- Sink runs in the IO monad and takes any printfable argument and returns
> () when pipe completes.
> displaySink :: PrintfArg a => Sink a IO ()
> displaySink = do
>   m <- C.await
>   case m of
>     Nothing -> return ()  -- if nothing comes in, just exit
>     Just x -> do
>       liftIO $ printf "Command not implemented (conduit): '%s'\n" x
>       displaySink
>
> main = do
>   hSetBuffering stdout NoBuffering
>   commandSource $$ displaySink
>   runPipe $ commandProducer >+> displayConsumer
>
>
> commandProducer :: PrintfArg a => Producer a String IO ()
> commandProducer = do
>   x <- lift getLine
>   if x == "exit"
>     then return ()
>     else P.yield x >> commandProducer
>
> displayConsumer :: Consumer String IO ()
> displayConsumer = forever $ P.await >>= lift . printf "Command not
> implemented (pipes): '%s'\n"
>
> There are some utility function to shorten some of these definitions a bit
> in conduit.  These two examples are equivalent.  But basically you are
> creating a pipeline, the first of which gets commands until it gets an exit
> and then sends them down the pipeline (as a string).  The second piece of
> the pipe accepts anything that is printfable and prints it.  It will stop
> when the upstream stops sending it strings to print.  The point here is
> that you have little functions that you can compose together with other
> functions and create something bigger where none of the pieces interfere
> with each other or break the IO abstraction.
>
> As to which of these libraries you should try?  Conduits is a bit more
> straight forward and has a lot more documentation and supporting
> libraries.  Pipes is a lot more flexible in that you could send things both
> directions along the pipe in the future when you become proficient with the
> library.
>
>
>
>
> On Sun, Mar 31, 2013 at 9:38 PM, Ovidiu D <[email protected]> wrote:
>
>> 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 <[email protected]> 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 <[email protected]> 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
>>>> [email protected]
>>>> http://www.haskell.org/mailman/listinfo/beginners
>>>>
>>>>
>>>
>>> _______________________________________________
>>> Beginners mailing list
>>> [email protected]
>>> http://www.haskell.org/mailman/listinfo/beginners
>>>
>>>
>>
>> _______________________________________________
>> Beginners mailing list
>> [email protected]
>> http://www.haskell.org/mailman/listinfo/beginners
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
<http://www.haskell.org/pipermail/beginners/attachments/20130331/edb61b49/attachment-0001.htm>

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

Message: 2
Date: Mon, 1 Apr 2013 12:14:34 +0800
From: Lyndon Maydwell <[email protected]>
Subject: Re: [Haskell-beginners] [IO String] to IO [String]
To: The Haskell-Beginners Mailing List - Discussion of primarily
        beginner-level topics related to Haskell <[email protected]>
Message-ID:
        <cam5qztwf7uwfsqbyugbsgn7smos+bumum_kjq4rk2ymxvej...@mail.gmail.com>
Content-Type: text/plain; charset="utf-8"

Interact should be able to handle line-by-line interaction as per this
example, it should even be able to handle the exit case thanks to laziness:

> main :: IO ()
> main = interact (unlines . map reverse . lines . untilexit)
>
> untilexit :: String -> String
> untilexit ('e':'x':'i':'t':_) = []
> untilexit (c:t)               = c : untilexit t
> untilexit []                  = []

There will be a lot of things that it won't be able to do however.


On Mon, Apr 1, 2013 at 5:49 AM, Ovidiu D <[email protected]> wrote:

> My problem with interact was that it doesn't give me the line when the
> user hits enter but instead it gives me all the lines at once when stdin is
> closed (unless I did something wrong)
>
> The other problem is that I want to stop the command processing when the
> user types the command "exit" and it seems interact can't do that.
>
>
> On Sun, Mar 31, 2013 at 2:52 PM, Lyndon Maydwell <[email protected]>wrote:
>
>> Depending on what you're doing with the lines, it may be worth checking
>> out the `interact` function as well :-)
>>
>>
>> On Sun, Mar 31, 2013 at 7:42 PM, Kim-Ee Yeoh <[email protected]> wrote:
>>
>>> On Sun, Mar 31, 2013 at 5:19 PM, Ovidiu D <[email protected]> wrote:
>>> > I would like to make this function to have the signature
>>> > f : IO [String]
>>> > ...such that I can get rid of the IO monad and pass the pure string
>>> list to
>>> > the processing function.
>>>
>>> You could use:
>>>
>>> getContents >>= lines :: IO [String]
>>>
>>> -- Kim-Ee
>>>
>>> _______________________________________________
>>> Beginners mailing list
>>> [email protected]
>>> http://www.haskell.org/mailman/listinfo/beginners
>>>
>>
>>
>> _______________________________________________
>> Beginners mailing list
>> [email protected]
>> http://www.haskell.org/mailman/listinfo/beginners
>>
>>
>
> _______________________________________________
> Beginners mailing list
> [email protected]
> http://www.haskell.org/mailman/listinfo/beginners
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
<http://www.haskell.org/pipermail/beginners/attachments/20130401/e4768273/attachment-0001.htm>

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

Message: 3
Date: Mon, 1 Apr 2013 11:15:06 +0300
From: Ovidiu D <[email protected]>
Subject: Re: [Haskell-beginners] [IO String] to IO [String]
To: The Haskell-Beginners Mailing List - Discussion of primarily
        beginner-level topics related to Haskell <[email protected]>
Message-ID:
        <CAKVsE7vNCd+tSAh5nUEOPESz26y=bynv4sqe1sfy0hb-3bx...@mail.gmail.com>
Content-Type: text/plain; charset="iso-8859-1"

Thanks.

I can see it working but I don't undestand why does untilexit actually stop
the processing. Can you explain that?

Also how could I display a prompt before reading each line?



On Mon, Apr 1, 2013 at 7:14 AM, Lyndon Maydwell <[email protected]> wrote:

> Interact should be able to handle line-by-line interaction as per this
> example, it should even be able to handle the exit case thanks to laziness:
>
> > main :: IO ()
> > main = interact (unlines . map reverse . lines . untilexit)
> >
> > untilexit :: String -> String
> > untilexit ('e':'x':'i':'t':_) = []
> > untilexit (c:t)               = c : untilexit t
> > untilexit []                  = []
>
> There will be a lot of things that it won't be able to do however.
>
>
> On Mon, Apr 1, 2013 at 5:49 AM, Ovidiu D <[email protected]> wrote:
>
>> My problem with interact was that it doesn't give me the line when the
>> user hits enter but instead it gives me all the lines at once when stdin is
>> closed (unless I did something wrong)
>>
>> The other problem is that I want to stop the command processing when the
>> user types the command "exit" and it seems interact can't do that.
>>
>>
>> On Sun, Mar 31, 2013 at 2:52 PM, Lyndon Maydwell <[email protected]>wrote:
>>
>>> Depending on what you're doing with the lines, it may be worth checking
>>> out the `interact` function as well :-)
>>>
>>>
>>> On Sun, Mar 31, 2013 at 7:42 PM, Kim-Ee Yeoh <[email protected]> wrote:
>>>
>>>> On Sun, Mar 31, 2013 at 5:19 PM, Ovidiu D <[email protected]> wrote:
>>>> > I would like to make this function to have the signature
>>>> > f : IO [String]
>>>> > ...such that I can get rid of the IO monad and pass the pure string
>>>> list to
>>>> > the processing function.
>>>>
>>>> You could use:
>>>>
>>>> getContents >>= lines :: IO [String]
>>>>
>>>> -- Kim-Ee
>>>>
>>>> _______________________________________________
>>>> Beginners mailing list
>>>> [email protected]
>>>> http://www.haskell.org/mailman/listinfo/beginners
>>>>
>>>
>>>
>>> _______________________________________________
>>> Beginners mailing list
>>> [email protected]
>>> http://www.haskell.org/mailman/listinfo/beginners
>>>
>>>
>>
>> _______________________________________________
>> Beginners mailing list
>> [email protected]
>> http://www.haskell.org/mailman/listinfo/beginners
>>
>>
>
> _______________________________________________
> Beginners mailing list
> [email protected]
> http://www.haskell.org/mailman/listinfo/beginners
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
<http://www.haskell.org/pipermail/beginners/attachments/20130401/053bd831/attachment.htm>

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

_______________________________________________
Beginners mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/beginners


End of Beginners Digest, Vol 58, Issue 3
****************************************

Reply via email to