How to print a string (lazily)

Hello, I've been studying more Haskell and I've improved a lot. But I just hit a small problem. I want to print all the elements of a linst (putStr). I'd like to write something like this: print_list [] = do putStr "" print_list (x:xs) = (do putStr x) && print_list xs I know this is wrong, but I hope you can see what I'm trying to do. I know of other ways I could print a list. For example: print_list xs = do putStr(join xs) where join [] = "" join (x:xs) = (show x) ++ "\n" ++ join xs But the thing is, I want to write a lazy version of this function. It's not that I need such a function, I'm just trying to learn Haskell. Any suggestions? Question: What do you call a function that has side-effects? (like putStr) I know that "function" is the wrong term. Cheers, Daniel. -- /\/`) http://oooauthors.org /\/_/ http://opendocumentfellowship.org /\/_/ \/_/ I am not over-weight, I am under-tall. /

Daniel Carrera wrote:
print_list xs = do putStr(join xs) where join [] = "" join (x:xs) = (show x) ++ "\n" ++ join xs
print_list xs = mapM putStrLn xs
Question: What do you call a function that has side-effects? (like putStr) I know that "function" is the wrong term.
"action", "command", "program", etc. HTH Christian

On Tuesday 03 Jan 2006 5:37 pm, Christian Maeder wrote:
Daniel Carrera wrote:
Question: What do you call a function that has side-effects? (like putStr) I know that "function" is the wrong term.
"action", "command", "program", etc.
Actually (at the risk of appearing pedantic), I think it's important to make clear that "function" *is* the correct term for putStr.. putStr :: String -> IO () It's expressions like (putStr "Hello World") of type IO <something> that are (what I would call) "actions". Haskell has no name for "functions that have side-effects". They don't exist (well not unless you're grossly abusing unsafePerformIO). Regards -- Adrian Hey

Daniel Carrera wrote:
Hello,
I've been studying more Haskell and I've improved a lot. But I just hit a small problem. I want to print all the elements of a linst (putStr). I'd like to write something like this:
print_list [] = do putStr "" print_list (x:xs) = (do putStr x) && print_list xs
I know this is wrong, but I hope you can see what I'm trying to do.
I know of other ways I could print a list. For example:
print_list xs = do putStr(join xs) where join [] = "" join (x:xs) = (show x) ++ "\n" ++ join xs
But the thing is, I want to write a lazy version of this function. It's not that I need such a function, I'm just trying to learn Haskell.
Any suggestions?
Question: What do you call a function that has side-effects? (like putStr) I know that "function" is the wrong term.
Cheers, Daniel.
I sometimes call a function with side-effects in IO a "command". But the terms are fungible. But calling putStr a "function" is correct. It is not a "pure function" however. What does lazy printing mean? I assume it means you evaluate the head of the list, print it, then recursively do this for the tail of the list. With an infinite list you will get inifinite output. I assume it does not mean you evaluate the whole list before printing anything. This would prevent infinite lists from producing output. (mapM_ putStr) or (mapM_ putStrLn) will do what you want. All of these commands show work, even if hw is inifitely long: let printList [] = return () printList (x:xs) = do putStrLn x printList xs main = do let hw = ["Hello"," ","World","!"] mapM_ putStr hw mapM_ putStrLn hw putStr (unlines hw) -- see also: unwords, words, lines printList hw -- Chris

On Tue, 3 Jan 2006, Chris Kuklewicz wrote: ...
I sometimes call a function with side-effects in IO a "command". But the terms are fungible. But calling putStr a "function" is correct. It is not a "pure function" however.
Is that the standard party line? I mean, we all know its type and semantics, whatever you want to call them, but if we want to put names to things, I had the impression that the IO monad is designed to work in a pure functional language - so that the functions are indeed actually pure, including putStr. It's the monad that actually incurs the side effects. Or something like that. So it isn't at all necessary to have another word for functions of type IO a. Donn Cave, donn@drizzle.com

On Tuesday 03 Jan 2006 6:11 pm, Donn Cave wrote:
On Tue, 3 Jan 2006, Chris Kuklewicz wrote: ...
I sometimes call a function with side-effects in IO a "command". But the terms are fungible. But calling putStr a "function" is correct. It is not a "pure function" however.
Is that the standard party line?
I don't think so. putStr certainly is a pure function. Try running.. main :: IO () main = let action = putStr "Bye" in action `seq` action ..and see what happens. Regards -- Adrian Hey

On 03/01/06, Donn Cave
On Tue, 3 Jan 2006, Chris Kuklewicz wrote: ...
I sometimes call a function with side-effects in IO a "command". But the terms are fungible. But calling putStr a "function" is correct. It is not a "pure function" however.
Is that the standard party line? I mean, we all know its type and semantics, whatever you want to call them, but if we want to put names to things, I had the impression that the IO monad is designed to work in a pure functional language - so that the functions are indeed actually pure, including putStr. It's the monad that actually incurs the side effects. Or something like that. So it isn't at all necessary to have another word for functions of type IO a.
I'd say it depends on the way that you're thinking about it. Strictly speaking, putStr is a pure function which returns an action. It's also referentially transparent, since it always returns the same action for the same string. However, if you think of functions a -> IO b as the arrows a -> b in a new category where composition is Kleisli composition: (@@) :: Monad m => (a -> m b) -> (t -> m a) -> (t -> m b) y @@ x = \u -> x u >>= y Then these arrows are "effectful" and would be considered impure. I think I prefer the first explanation, as it's a somewhat important property that the same action is computed for the same input. This doesn't hold of side-effectful arrows in general. Note that with Hughes' Arrows, this restriction can (often quite cleverly) be side-stepped in order to make some rather major optimisations. - Cale

Donn Cave wrote:
I sometimes call a function with side-effects in IO a "command". But the terms are fungible. But calling putStr a "function" is correct. It is not a "pure function" however.
Is that the standard party line? I mean, we all know its type and semantics, whatever you want to call them, but if we want to put names to things, I had the impression that the IO monad is designed to work in a pure functional language - so that the functions are indeed actually pure, including putStr.
putStr is a pure function, but it isn't a "pure function" ;)
OTOH, getLine isn't even a function, just a value.
--
Glynn Clements

Chris Kuklewicz wrote:
What does lazy printing mean?
I assume it means you evaluate the head of the list, print it, then recursively do this for the tail of the list. With an infinite list you will get inifinite output.
I assume it does not mean you evaluate the whole list before printing anything. This would prevent infinite lists from producing output.
Yes, that's exactly what I had in mind. I wanted to print [1..] (an infinite list) with each number on a different line. Thanks for the help. Yes, the function works now.
main = do let hw = ["Hello"," ","World","!"] mapM_ putStr hw mapM_ putStrLn hw putStr (unlines hw) -- see also: unwords, words, lines printList hw
Cool. I didn't know about (un)words and unlines. Cheers, Daniel. -- /\/`) http://oooauthors.org /\/_/ http://opendocumentfellowship.org /\/_/ \/_/ I am not over-weight, I am under-tall. /

Hi,
All Haskell functions are lazy, hence there is no need to "write a
lazy version" of your print_list function. I think the function you
probably want is:
putStr (unlines xs)
This uses the bulid in unlines function, which is similar in spirit to
join (you get more quotes, which I guess you don't want)
The equivalent in monad'y programming is:
mapM putStrLn xs
The first one has fewer monads, so I prefer it, but take your pick :)
Thanks
Neil
On 1/3/06, Daniel Carrera
Hello,
I've been studying more Haskell and I've improved a lot. But I just hit a small problem. I want to print all the elements of a linst (putStr). I'd like to write something like this:
print_list [] = do putStr "" print_list (x:xs) = (do putStr x) && print_list xs
I know this is wrong, but I hope you can see what I'm trying to do.
I know of other ways I could print a list. For example:
print_list xs = do putStr(join xs) where join [] = "" join (x:xs) = (show x) ++ "\n" ++ join xs
But the thing is, I want to write a lazy version of this function. It's not that I need such a function, I'm just trying to learn Haskell.
Any suggestions?
Question: What do you call a function that has side-effects? (like putStr) I know that "function" is the wrong term.
Cheers, Daniel. -- /\/`) http://oooauthors.org /\/_/ http://opendocumentfellowship.org /\/_/ \/_/ I am not over-weight, I am under-tall. / _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Neil Mitchell wrote:
All Haskell functions are lazy, hence there is no need to "write a lazy version" of your print_list function. I think the function you probably want is:
putStr (unlines xs)
Hhmm... that does work, and I'm a bit surprised that it does. I guess I'm still stuck in the eager computation mindset. I would expect putStr to have to wait for the (unlines xs) to be finished before doing any printing, but it doesn't. Some day I'll get the hang of this lazy evaluation thing. :)
The first one has fewer monads, so I prefer it, but take your pick :)
Monads scare me, so I'll pick the first :) Thanks! Cheers, Daniel. -- /\/`) http://oooauthors.org /\/_/ http://opendocumentfellowship.org /\/_/ \/_/ I am not over-weight, I am under-tall. /

On 1/3/06, Daniel Carrera
Neil Mitchell wrote:
All Haskell functions are lazy, hence there is no need to "write a lazy version" of your print_list function. I think the function you probably want is:
putStr (unlines xs)
Hhmm... that does work, and I'm a bit surprised that it does. I guess I'm still stuck in the eager computation mindset. I would expect putStr to have to wait for the (unlines xs) to be finished before doing any printing, but it doesn't.
Some day I'll get the hang of this lazy evaluation thing. :)
It does, in a sense, but since unlines is lazy (just like *everything else* in Haskell) it won't actually *do* anything until putStr demands an element from the result. /S -- Sebastian Sylvan +46(0)736-818655 UIN: 44640862

On Jan 3, 2006, at 6:30 PM, Sebastian Sylvan wrote:
On 1/3/06, Daniel Carrera
wrote: Neil Mitchell wrote:
All Haskell functions are lazy, hence there is no need to "write a lazy version" of your print_list function. I think the function you probably want is:
putStr (unlines xs)
Hhmm... that does work, and I'm a bit surprised that it does. I guess I'm still stuck in the eager computation mindset. I would expect putStr to have to wait for the (unlines xs) to be finished before doing any printing, but it doesn't.
Some day I'll get the hang of this lazy evaluation thing. :)
It does, in a sense, but since unlines is lazy (just like *everything else* in Haskell) it won't actually *do* anything until putStr demands an element from the result.
... and, significantly, putStr will demand those elements one at a time; each element of the list is, in turn, evaluated lazily, producing (a) a next element and (b) a thunk representing the rest of the list. In your example 'join' function, join [] = "" join (x:xs) = (show x) ++ "\n" ++ join xs the caller will demand the first element of the list, which will force the evaluation of (show x) but it will not immediately force the evaluation of (join xs). That part stays as it is, living life as a thunk, until the caller has demanded all the preceding elements and still wants more. hth, Ezra

Am Dienstag, 3. Januar 2006 19:15 schrieb Daniel Carrera:
Neil Mitchell wrote:
All Haskell functions are lazy, hence there is no need to "write a lazy version" of your print_list function. I think the function you probably want is:
putStr (unlines xs)
Hhmm... that does work, and I'm a bit surprised that it does. I guess I'm still stuck in the eager computation mindset. I would expect putStr to have to wait for the (unlines xs) to be finished before doing any printing, but it doesn't.
(unlines xs) is only evaluated on demand. Think of putStr as defined as follows: putStr :: String -> IO () putStr [] = return () putStr (x : xs) = do putChar x putStr xs Every character of the string is evaluated when it is needed by putChar x, not earlier. So the argument of putStr is evaluated lazily.
[...]
Some day I'll get the hang of this lazy evaluation thing. :)
Yes. :-) Lazy evaluation is really powerful. ;-)
The first one has fewer monads, so I prefer it, but take your pick :)
Monads scare me, so I'll pick the first :) Thanks!
It is preferable because it does more of the work without imperative programming.
Cheers, Daniel.
Best wishes, Wolfgang

On Tue, Jan 03, 2006 at 05:49:07PM +0000, Neil Mitchell wrote:
All Haskell functions are lazy, hence there is no need to "write a lazy version" of your print_list function. I think the function you probably want is:
putStr (unlines xs)
This uses the bulid in unlines function, which is similar in spirit to join (you get more quotes, which I guess you don't want)
The equivalent in monad'y programming is:
mapM putStrLn xs
The first one has fewer monads, so I prefer it, but take your pick :)
Nitpicking a bit to prevent possible confusion: a monad is a *type constructor*, not an expression. In both variants above you are dealing with two monads - IO and [] - however, the Monad instance for [] is not used. Best regards Tomasz -- I am searching for programmers who are good at least in (Haskell || ML) && (Linux || FreeBSD || math) for work in Warsaw, Poland

On 1/3/06, Daniel Carrera
Hello,
I've been studying more Haskell and I've improved a lot. But I just hit a small problem. I want to print all the elements of a linst (putStr). I'd like to write something like this:
print_list [] = do putStr "" print_list (x:xs) = (do putStr x) && print_list xs
Others have already replied with a solution, but it looks to me like what you're "missing" is how to sequence commands, which is the whole purpose of the "do" notation. print_list [] = return () print_list (x:xs) = do putStr x print_list xs The do notation is used here to sequence to IO actions (which answers your second question), first it prints out the first character in the string, then it calls itself recursively to print the rest of the list. The empty list shouldn't print an empty string, it should do nothing (that is, just return IO () because that's the return type of print_list) /S -- Sebastian Sylvan +46(0)736-818655 UIN: 44640862

Sebastian Sylvan wrote:
Others have already replied with a solution, but it looks to me like what you're "missing" is how to sequence commands, which is the whole purpose of the "do" notation.
print_list [] = return () print_list (x:xs) = do putStr x print_list xs
The do notation is used here to sequence to IO actions (which answers your second question), first it prints out the first character in the string, then it calls itself recursively to print the rest of the list.
Thanks! And yes, I'm just learning how to sequence commands/actions, so I know I'm missing a lot.
The empty list shouldn't print an empty string, it should do nothing (that is, just return IO () because that's the return type of print_list)
Yeah... I just didn't know how to "do nothing" with Haskell. Thanks! Cheers, Daniel. -- /\/`) http://oooauthors.org /\/_/ http://opendocumentfellowship.org /\/_/ \/_/ I am not over-weight, I am under-tall. /

Daniel Carrera wrote:
I've been studying more Haskell and I've improved a lot. But I just hit a small problem. I want to print all the elements of a linst (putStr). I'd like to write something like this:
print_list [] = do putStr ""
This looks as if you're confused. The keyword "do" is completely redundant. "do" does not mean "please ignore all rules and allow side effects", it rather means "please build a new action by sequencing what follows". So "do" with only one action after it is useless (and a sign of confusion). Have you ever heard about the "command" and "composite" design patterns? Well, in Haskell, you get them for free with monads.
print_list (x:xs) = (do putStr x) && print_list xs
print_list (x:xs) = do putStr x ; print_list xs
print_list xs = do putStr(join xs) where join [] = "" join (x:xs) = (show x) ++ "\n" ++ join xs
But the thing is, I want to write a lazy version of this function.
What's not lazy about it? If you think, join has to "complete" "before" putStr can be called, simply forget it. Those words don't even make sense in a lazy functional setting. Udo. -- Lost: gray and white female cat. Answers to electric can opener.

On Tue, Jan 03, 2006 at 10:28:54PM +0100, Udo Stenzel wrote:
Daniel Carrera wrote:
print_list [] = do putStr ""
This looks as if you're confused. The keyword "do" is completely redundant. "do" does not mean "please ignore all rules and allow side effects", it rather means "please build a new action by sequencing what follows". So "do" with only one action after it is useless (and a sign of confusion).
Perhaps you are right, but this can also be a sign of version-control awareness, and I know Daniel uses darcs. I often place a single command in a do-block, because I want future changes to touch as little lines as possible. Consider: f = putStrLn "b" and f = do putStrLn "b" If you'll later add more commands, you'll get something like: f = do x <- g putStrLn "b" putStrLn x which is much closer to the reduntant-do variant. Best regards Tomasz -- I am searching for programmers who are good at least in (Haskell || ML) && (Linux || FreeBSD || math) for work in Warsaw, Poland
participants (13)
-
Adrian Hey
-
Cale Gibbard
-
Chris Kuklewicz
-
Christian Maeder
-
Daniel Carrera
-
Donn Cave
-
Ezra Cooper
-
Glynn Clements
-
Neil Mitchell
-
Sebastian Sylvan
-
Tomasz Zielonka
-
Udo Stenzel
-
Wolfgang Jeltsch