
Hi all, there is something very basic that it seems escaped me. For example with the following program f and g have type IO () and I can thread a value between the two using a file. Can I do the exact same (not changing the types of f and g) without a file?* f,g :: IO () **f = withFile "toto" WriteMode (flip hPutStr "toto") g = withFile "toto" ReadMode hGetLine >>= putStrLn main = f >> g* Thanks and cheers, Corentin

On Wed, Aug 29, 2012 at 10:58 AM, Corentin Dupont
Hi all, there is something very basic that it seems escaped me. For example with the following program f and g have type IO () and I can thread a value between the two using a file. Can I do the exact same (not changing the types of f and g) without a file?
f,g :: IO () f = withFile "toto" WriteMode (flip hPutStr "toto") g = withFile "toto" ReadMode hGetLine >>= putStrLn main = f >> g
Of course: f,g :: IO () f = putStr "Answer: " g = print 42 Main> f >> g Answer: 42 The () is threaded by >>, not the file content -- MM

Hi Mihai,
maybe the term "thread" in my mail is not correct.
What I mean is that a value gets stored by f and discovered by g.
*f,g :: IO ()
f = withFile "toto" WriteMode (flip hPutStr "42")
g = withFile "toto" ReadMode hGetLine >>= (\s -> putStrLn $ "Answer:" ++ s)
main = f >> g*
Is it possible to do the same without files (the types must remain IO())?
On Wed, Aug 29, 2012 at 11:04 AM, Mihai Maruseac
On Wed, Aug 29, 2012 at 10:58 AM, Corentin Dupont
wrote: Hi all, there is something very basic that it seems escaped me. For example with the following program f and g have type IO () and I can thread a value between the two using a file. Can I do the exact same (not changing the types of f and g) without a file?
f,g :: IO () f = withFile "toto" WriteMode (flip hPutStr "toto") g = withFile "toto" ReadMode hGetLine >>= putStrLn main = f >> g
Of course:
f,g :: IO () f = putStr "Answer: " g = print 42
Main> f >> g Answer: 42
The () is threaded by >>, not the file content
-- MM

Of course, not.
What you do with a file is a sequence of side effects done by f, then g.
If you want to reuse the value of type IO a returned by f, your g
function would need to have type g:: a->IO ()
so that you combine the actions: f >>= g
On 29 August 2012 02:21, Corentin Dupont
Hi Mihai, maybe the term "thread" in my mail is not correct. What I mean is that a value gets stored by f and discovered by g.
f,g :: IO () f = withFile "toto" WriteMode (flip hPutStr "42") g = withFile "toto" ReadMode hGetLine >>= (\s -> putStrLn $ "Answer:" ++ s) main = f >> g
Is it possible to do the same without files (the types must remain IO())?
On Wed, Aug 29, 2012 at 11:04 AM, Mihai Maruseac
wrote: On Wed, Aug 29, 2012 at 10:58 AM, Corentin Dupont
wrote: Hi all, there is something very basic that it seems escaped me. For example with the following program f and g have type IO () and I can thread a value between the two using a file. Can I do the exact same (not changing the types of f and g) without a file?
f,g :: IO () f = withFile "toto" WriteMode (flip hPutStr "toto") g = withFile "toto" ReadMode hGetLine >>= putStrLn main = f >> g
Of course:
f,g :: IO () f = putStr "Answer: " g = print 42
Main> f >> g Answer: 42
The () is threaded by >>, not the file content
-- MM
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
-- Best, Eugene Perederey

On 29 August 2012 10:21, Corentin Dupont
*f,g :: IO () f = withFile "toto" WriteMode (flip hPutStr "42") g = withFile "toto" ReadMode hGetLine >>= (\s -> putStrLn $ "Answer:" ++ s) main = f >> g*
Is it possible to do the same without files (the types must remain IO())?
One can use an IORef to get a similar effect. import Data.IORef import System.IO.Unsafe {-# NOINLINE toto #-} toto :: IORef String toto = unsafePerformIO (newIORef "") f,g :: IO () f = writeIORef toto "42" g = readIORef toto >>= (\s -> putStrLn $ "Answer:" ++ s) main = f >> g HTH, Ozgur

Thanks Eugene and Ozgur.
I also looked on the side of IORef, but it doesn't looked to be a good
solution since we have to use unsafePerformIO.
I have a big program to modify, and I want to pass some new data to
existing functions of type IO(). I'd like to avoid changing all the
function's types down the chain... What is the best way to do that?
On Wed, Aug 29, 2012 at 11:43 AM, Ozgur Akgun
On 29 August 2012 10:21, Corentin Dupont
wrote: *f,g :: IO () f = withFile "toto" WriteMode (flip hPutStr "42") g = withFile "toto" ReadMode hGetLine >>= (\s -> putStrLn $ "Answer:" ++ s) main = f >> g*
Is it possible to do the same without files (the types must remain IO())?
One can use an IORef to get a similar effect.
import Data.IORef import System.IO.Unsafe
{-# NOINLINE toto #-} toto :: IORef String toto = unsafePerformIO (newIORef "")
f,g :: IO () f = writeIORef toto "42" g = readIORef toto >>= (\s -> putStrLn $ "Answer:" ++ s)
main = f >> g
HTH, Ozgur

On Wed, Aug 29, 2012 at 12:00:50PM +0200, Corentin Dupont wrote:
Thanks Eugene and Ozgur. I also looked on the side of IORef, but it doesn't looked to be a good solution since we have to use unsafePerformIO.
I have a big program to modify, and I want to pass some new data to existing functions of type IO(). I'd like to avoid changing all the function's types down the chain... What is the best way to do that?
There is no good way. IORef is probably the best, but as you correctly point out, it is quite ugly. The fact that you have to change your program's types is a feature, not a bug. One of Haskell's great strengths is that the types make plain any communication which can take place between different components. If you want to go behind the type system's back and add hidden communication channels, you might as well be writing in C, and should not be surprised that there is no good way to do it. -Brent
participants (5)
-
Brent Yorgey
-
Corentin Dupont
-
Eugene Perederey
-
Mihai Maruseac
-
Ozgur Akgun