A basic misunderstanding of how to program with IO

Sorry for such a beginner-y question, but is there a way to make a function like: interact :: String -> Resp interact txt = putStrLn txt rsp <- getLine return parseResp rsp parseResp :: String -> Resp Or is that simply a wrong way of programming in Haskell with IO? Thanks (and apologies), -- kov

I might have misunderstood you, but what about using the existing interact
function:
http://haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/Prelude.html#...
And for your interact, since it is not in the IO monad, you cannot write
such a function. [ don't tell him about the unsafePerformIO :) ]
I am sure you'll get better answers.
Best,
On 8 May 2010 16:55, Ken Overton
Sorry for such a beginner-y question, but is there a way to make a function like:
interact :: String -> Resp interact txt = putStrLn txt rsp <- getLine return parseResp rsp
parseResp :: String -> Resp
Or is that simply a wrong way of programming in Haskell with IO?
Thanks (and apologies),
-- kov_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
-- Ozgur Akgun

Thanks; I guess my 'problem' is that I naturally gravitate to a function that returns *the result of the interaction* rather than IO, but that seems impossible anywhere IO is used.
So looking at the 'real' interact function, I guess the Haskell way is to pass in my function that acts on the data that was read. I guess that makes sense as then I can separate all my 'action' code from IO code. Is that a reasonable understanding?
Sorry if this was so obvious; is this kind of pattern documented in greater detail somewhere? I haven't noticed anything yet, but maybe I've been hoogling the wrong names.
--kov
________________________________________
From: Ozgur Akgun [ozgurakgun@gmail.com]
Sent: Saturday, May 08, 2010 12:09 PM
To: Ken Overton
Cc: beginners@haskell.org
Subject: Re: [Haskell-beginners] A basic misunderstanding of how to program with IO
I might have misunderstood you, but what about using the existing interact function: http://haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/Prelude.html#...
And for your interact, since it is not in the IO monad, you cannot write such a function. [ don't tell him about the unsafePerformIO :) ]
I am sure you'll get better answers.
Best,
On 8 May 2010 16:55, Ken Overton

Excerpts from Ken Overton's message of Sat May 08 12:20:12 -0400 2010:
Thanks; I guess my 'problem' is that I naturally gravitate to a function that returns *the result of the interaction* rather than IO, but that seems impossible anywhere IO is used.
That's correct; there's no (normal) way to write a function IO a -> a.
So looking at the 'real' interact function, I guess the Haskell way is to pass in my function that acts on the data that was read. I guess that makes sense as then I can separate all my 'action' code from IO code. Is that a reasonable understanding?
That is also correct. Notice the types inside your do-block: do rsp <- getLine getLine is of type IO String, but rsp is of type String! As long as we're in a do-block (which "keeps" us in the IO monad), we can temporarily extract the real value without IO to pass to a pure function. Cheers, Edward

On 8 May 2010, at 17:09, Ozgur Akgun wrote:
I might have misunderstood you, but what about using the existing interact function: http://haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/Prelude.html#...
And for your interact, since it is not in the IO monad, you cannot write such a function. [ don't tell him about the unsafePerformIO :) ]
Uh, interact absolutely *is* in the IO monad, and is totally implementable without unsafePerformIO, like this: interact f = putStr =<< f <$> getContents Bob

On 8 May 2010 17:44, Thomas Davie
On 8 May 2010, at 17:09, Ozgur Akgun wrote:
I might have misunderstood you, but what about using the existing interact function: http://haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/Prelude.html#...
And for your interact, since it is not in the IO monad, you cannot write such a function. [ don't tell him about the unsafePerformIO :) ]
Uh, interact absolutely *is* in the IO monad, and is totally implementable without unsafePerformIO, like this:
Upps now I need to clarify myself I guess. I said "your interact is not in the IO monad", because the interact OP defined had the type: interact :: String -> Resp Which obviously is not in the IO monad, if he is not hiding something in Resp (looks unlikely to me)
interact f = putStr =<< f <$> getContents
Bob
And of course, interact is something implementable :) Best, Ozgur

On 05/08/10 11:55, Ken Overton wrote:
Sorry for such a beginner-y question, but is there a way to make a function like:
interact :: String -> Resp interact txt = putStrLn txt rsp<- getLine return parseResp rsp
parseResp :: String -> Resp
Or is that simply a wrong way of programming in Haskell with IO?
I think, yes your function looks close to typical Haskell, you're just missing a "do", a pair of parentheses, and an "IO": interact :: String -> IO Resp interact txt = do putStrLn txt rsp <- getLine return (parseResp rsp) parseResp :: String -> Resp Does that make sense to you? Would you like more detailed explanation of the changes? -Isaac

I think, yes your function looks close to typical Haskell, you're just missing a "do", a pair of parentheses, and an "IO":
Sorry, I'd definitely intended the 'do' to be there.
interact :: String -> IO Resp
Thanks Isaac; so after I've called this how do I get the Resp value back out of the returned IO? Regards, --kov

On 05/09/10 19:30, Ken Overton wrote:
I think, yes your function looks close to typical Haskell, you're just missing a "do", a pair of parentheses, and an "IO":
Sorry, I'd definitely intended the 'do' to be there.
interact :: String -> IO Resp
Thanks Isaac; so after I've called this how do I get the Resp value back out of the returned IO?
By using it in some other piece of IO. For example, main :: IO () main = do resp <- interact "hi there!" let modifiedResp = some function involving resp ... You see, "IO" lets you distinguish between functions/values that require IO actions, and those that are completely pure (always give the same result, given the same arguments, as is typical in mathematics). Just use your patience! : Every function that uses that resulting Resp will have to be in IO. This is not as bad as it seems, because most of the processing of the Resp can be pure again: for example, the way you call parseResp which is a pure function, or "some function involving resp" in my example above. i'd suggest 1. Practice. The typechecker will tell you when you get it wrong. 2. Generally try to mark less of your code as "IO", because this is good style ( -- it turns out to be easier to code [and refactor code] with pure functions, because you know they don't have side-effects, so you mostly don't need to worry about "when" or "how often" they're called.) -Isaac
participants (5)
-
Edward Z. Yang
-
Isaac Dupree
-
Ken Overton
-
Ozgur Akgun
-
Thomas Davie