
I have the function f which reads lines form the stdin and looks like this: f :: [IO String] f = getLine : f What I don't like is the fact that the line processing I'm doing will have to be in the IO Monad 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. Can I do this? Thanks

You can use sequence which will turn your [IO String] into a IO [String]. If you want to "map a function" along the way, you can use mapM (or traverse): That is: mapM :: (String -> IO b) -> [IO String] -> IO [b] For further reading, there is a paper about this function called The Essence of the Iterator Pattern. On 31/03/13 20:19, Ovidiu D wrote:
I have the function f which reads lines form the stdin and looks like this:
f :: [IO String] f = getLine : f
What I don't like is the fact that the line processing I'm doing will have to be in the IO Monad
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.
Can I do this?
Thanks
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
-- Tony Morris http://tmorris.net/

Try sequence :: Monad m => [m a] -> m [a] I thinkg sequence f :: IO [String] should be what you want. On 03/31/2013 12:19 PM, Ovidiu D wrote:
I have the function f which reads lines form the stdin and looks like this:
f :: [IO String] f = getLine : f
What I don't like is the fact that the line processing I'm doing will have to be in the IO Monad
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.
Can I do this?
Thanks
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

Unfortunately, with the definition f = getLine : f this will not work. 'sequence f' has to do *ALL* the IO before you can process even the first String in the resulting list. Since it is infinite, it will just sit there reading lines forever but never letting you process them. I think in this case using [IO String] is actually a good solution. -Brent On Sun, Mar 31, 2013 at 12:24:33PM +0200, Nathan Hüsken wrote:
Try
sequence :: Monad m => [m a] -> m [a]
I thinkg
sequence f :: IO [String]
should be what you want.
On 03/31/2013 12:19 PM, Ovidiu D wrote:
I have the function f which reads lines form the stdin and looks like this:
f :: [IO String] f = getLine : f
What I don't like is the fact that the line processing I'm doing will have to be in the IO Monad
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.
Can I do this?
Thanks
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

Right. I definitely want the lazy behavior.
Thanks
On Sun, Mar 31, 2013 at 1:29 PM, Brent Yorgey
Unfortunately, with the definition
f = getLine : f
this will not work. 'sequence f' has to do *ALL* the IO before you can process even the first String in the resulting list. Since it is infinite, it will just sit there reading lines forever but never letting you process them.
I think in this case using [IO String] is actually a good solution.
-Brent
Try
sequence :: Monad m => [m a] -> m [a]
I thinkg
sequence f :: IO [String]
should be what you want.
On 03/31/2013 12:19 PM, Ovidiu D wrote:
I have the function f which reads lines form the stdin and looks like
On Sun, Mar 31, 2013 at 12:24:33PM +0200, Nathan Hüsken wrote: this:
f :: [IO String] f = getLine : f
What I don't like is the fact that the line processing I'm doing will have to be in the IO Monad
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.
Can I do this?
Thanks
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

To elaborate a bit: you originally said "I don't like that the line processing I'm doing will have to be in the IO monad" -- but since you want the processing of the list of Strings to be interleaved with IO operations, you have no choice. Pure functions of type [String] -> [String] cannot have their evaluation interleaved with IO operations. Note that functions using lazy I/O such as getContents, readFile, etc. can create exceptions to this -- but these use unsafeInterleaveIO under the hood and are widely regarded as problematic. So you could try using unsafeInterleaveIO, but it is unsafe for a reason. I do not actually know what is required to ensure you are using it safely; perhaps someone else could elaborate on this. -Brent On Sun, Mar 31, 2013 at 01:48:23PM +0300, Ovidiu D wrote:
Right. I definitely want the lazy behavior.
Thanks
On Sun, Mar 31, 2013 at 1:29 PM, Brent Yorgey
wrote: Unfortunately, with the definition
f = getLine : f
this will not work. 'sequence f' has to do *ALL* the IO before you can process even the first String in the resulting list. Since it is infinite, it will just sit there reading lines forever but never letting you process them.
I think in this case using [IO String] is actually a good solution.
-Brent
Try
sequence :: Monad m => [m a] -> m [a]
I thinkg
sequence f :: IO [String]
should be what you want.
On 03/31/2013 12:19 PM, Ovidiu D wrote:
I have the function f which reads lines form the stdin and looks like
On Sun, Mar 31, 2013 at 12:24:33PM +0200, Nathan Hüsken wrote: this:
f :: [IO String] f = getLine : f
What I don't like is the fact that the line processing I'm doing will have to be in the IO Monad
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.
Can I do this?
Thanks
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

That makes perfect sense. Thanks for the detailed explanation.
On Sun, Mar 31, 2013 at 2:30 PM, Brent Yorgey
To elaborate a bit: you originally said "I don't like that the line processing I'm doing will have to be in the IO monad" -- but since you want the processing of the list of Strings to be interleaved with IO operations, you have no choice. Pure functions of type [String] -> [String] cannot have their evaluation interleaved with IO operations.
Note that functions using lazy I/O such as getContents, readFile, etc. can create exceptions to this -- but these use unsafeInterleaveIO under the hood and are widely regarded as problematic. So you could try using unsafeInterleaveIO, but it is unsafe for a reason. I do not actually know what is required to ensure you are using it safely; perhaps someone else could elaborate on this.
-Brent
Right. I definitely want the lazy behavior.
Thanks
On Sun, Mar 31, 2013 at 1:29 PM, Brent Yorgey
Unfortunately, with the definition
f = getLine : f
this will not work. 'sequence f' has to do *ALL* the IO before you can process even the first String in the resulting list. Since it is infinite, it will just sit there reading lines forever but never letting you process them.
I think in this case using [IO String] is actually a good solution.
-Brent
On Sun, Mar 31, 2013 at 12:24:33PM +0200, Nathan Hüsken wrote:
Try
sequence :: Monad m => [m a] -> m [a]
I thinkg
sequence f :: IO [String]
should be what you want.
On 03/31/2013 12:19 PM, Ovidiu D wrote:
I have the function f which reads lines form the stdin and looks
this:
f :: [IO String] f = getLine : f
What I don't like is the fact that the line processing I'm doing
will
have to be in the IO Monad
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
On Sun, Mar 31, 2013 at 01:48:23PM +0300, Ovidiu D wrote: like list
to the processing function.
Can I do this?
Thanks
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

On Sun, Mar 31, 2013 at 5:19 PM, Ovidiu D
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

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
On Sun, Mar 31, 2013 at 5:19 PM, Ovidiu D
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 Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

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
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
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
On Sun, Mar 31, 2013 at 5:19 PM, Ovidiu D
wrote: list to the processing function.
You could use:
getContents >>= lines :: IO [String]
-- Kim-Ee
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

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
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
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
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
On Sun, Mar 31, 2013 at 5:19 PM, Ovidiu D
wrote: list to the processing function.
You could use:
getContents >>= lines :: IO [String]
-- Kim-Ee
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

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
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
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
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
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
On Sun, Mar 31, 2013 at 5:19 PM, Ovidiu D
wrote: list to the processing function.
You could use:
getContents >>= lines :: IO [String]
-- Kim-Ee
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

The untilexit definition is pretty straightforward. You can see that the
the function operates on a string. There are two cases where nothing is
returned: "" and "exit" ++ rest.
In order to display a prompt before each input you will need to actually
display a prompt /after/ each line, and an additional prompt before you
start processing input.
On Mon, Apr 1, 2013 at 4:15 PM, Ovidiu D
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
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
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
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
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
On Sun, Mar 31, 2013 at 5:19 PM, Ovidiu D
wrote: list to the processing function.
You could use:
getContents >>= lines :: IO [String]
-- Kim-Ee
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

On Mon, Apr 1, 2013 at 11:52 AM, Lyndon Maydwell
The untilexit definition is pretty straightforward. You can see that the the function operates on a string. There are two cases where nothing is returned: "" and "exit" ++ rest.
Ok, that's clear. What I don't understand is why does it stop interact? It returns the same thing if the input is empty or if it starts with "exit". Why doesn't it stop interact when the input line is empty?
In order to display a prompt before each input you will need to actually display a prompt /after/ each line, and an additional prompt before you start processing input.
I was trying to do that but I was doing it wrong. Anyway this is the result which works as expected now, although I don't really understand why it stops at 'exit' import System.IO prompt = ">> " main :: IO () main = do hSetBuffering stdout NoBuffering putStr prompt interact $ display . map reverse . lines . untilexit display = concat . map appendPrompt where appendPrompt line = line ++ "\n" ++ prompt untilexit :: String -> String untilexit ('e':'x':'i':'t':_) = [] untilexit (c:t) = c : untilexit t untilexit [] = []

Ah I see what you're saying.
interact [1] uses hGetContents [2] to read the user-input. This is a
lazy-io function which is also used in readFile [3]. In the same way that
readFile won't read the entire file if its contents aren't used, neither
will interact. There is debate as to weather this is a good way to handle
(lol) IO, with other solutions including Conduit [4] and Pipes [5], but for
simple programs it is an elegant solution.
[1]
http://hackage.haskell.org/packages/archive/base/latest/doc/html/src/System-...
[2]
http://hackage.haskell.org/packages/archive/base/latest/doc/html/System-IO.h...
[3]
http://hackage.haskell.org/packages/archive/base/4.3.1.0/doc/html/src/System...
[4] http://hackage.haskell.org/package/conduit
[5] http://hackage.haskell.org/package/pipes
I hope this helps :)
On Mon, Apr 1, 2013 at 5:54 PM, Ovidiu D
On Mon, Apr 1, 2013 at 11:52 AM, Lyndon Maydwell
wrote: The untilexit definition is pretty straightforward. You can see that the the function operates on a string. There are two cases where nothing is returned: "" and "exit" ++ rest.
Ok, that's clear. What I don't understand is why does it stop interact? It returns the same thing if the input is empty or if it starts with "exit". Why doesn't it stop interact when the input line is empty?
In order to display a prompt before each input you will need to actually display a prompt /after/ each line, and an additional prompt before you start processing input.
I was trying to do that but I was doing it wrong. Anyway this is the result which works as expected now, although I don't really understand why it stops at 'exit'
import System.IO
prompt = ">> "
main :: IO () main = do hSetBuffering stdout NoBuffering putStr prompt interact $ display . map reverse . lines . untilexit
display = concat . map appendPrompt where appendPrompt line = line ++ "\n" ++ prompt
untilexit :: String -> String untilexit ('e':'x':'i':'t':_) = [] untilexit (c:t) = c : untilexit t untilexit [] = []
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

I understand. Thanks a lot for the explanation and for the documentation.
ovidiu
On Mon, Apr 1, 2013 at 2:17 PM, Lyndon Maydwell
Ah I see what you're saying.
interact [1] uses hGetContents [2] to read the user-input. This is a lazy-io function which is also used in readFile [3]. In the same way that readFile won't read the entire file if its contents aren't used, neither will interact. There is debate as to weather this is a good way to handle (lol) IO, with other solutions including Conduit [4] and Pipes [5], but for simple programs it is an elegant solution.
[1] http://hackage.haskell.org/packages/archive/base/latest/doc/html/src/System-... [2] http://hackage.haskell.org/packages/archive/base/latest/doc/html/System-IO.h... [3] http://hackage.haskell.org/packages/archive/base/4.3.1.0/doc/html/src/System... [4] http://hackage.haskell.org/package/conduit [5] http://hackage.haskell.org/package/pipes
I hope this helps :)
On Mon, Apr 1, 2013 at 5:54 PM, Ovidiu D
wrote: On Mon, Apr 1, 2013 at 11:52 AM, Lyndon Maydwell
wrote: The untilexit definition is pretty straightforward. You can see that the the function operates on a string. There are two cases where nothing is returned: "" and "exit" ++ rest.
Ok, that's clear. What I don't understand is why does it stop interact? It returns the same thing if the input is empty or if it starts with "exit". Why doesn't it stop interact when the input line is empty?
In order to display a prompt before each input you will need to actually display a prompt /after/ each line, and an additional prompt before you start processing input.
I was trying to do that but I was doing it wrong. Anyway this is the result which works as expected now, although I don't really understand why it stops at 'exit'
import System.IO
prompt = ">> "
main :: IO () main = do hSetBuffering stdout NoBuffering putStr prompt interact $ display . map reverse . lines . untilexit
display = concat . map appendPrompt where appendPrompt line = line ++ "\n" ++ prompt
untilexit :: String -> String untilexit ('e':'x':'i':'t':_) = [] untilexit (c:t) = c : untilexit t untilexit [] = []
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
participants (6)
-
Brent Yorgey
-
Kim-Ee Yeoh
-
Lyndon Maydwell
-
Nathan Hüsken
-
Ovidiu D
-
Tony Morris