Get and put a string in Haskell throws error - haskell

I found the following Haskell code, but I'm confused:
main = putStrLn "Enter 1st String:"
>> getLine
>>= \a -> read a
What do the two "greater than" symbols (>>) mean? A new statement?
What do the two "greater than" symbols followed by an equal sign (>>=) mean?
This Haskell code throws the following error:
a.hs:3:13:
No instance for (Read (IO t0)) arising from a use of ‘read’
In the expression: read a
In the second argument of ‘(>>=)’, namely ‘\ a -> read a’
In the expression:
putStrLn "Enter 1st String:" >> getLine >>= \ a -> read a

1) does two greater than symbols mean a new statement?
In this context, yes. In the IO monad, >> is a rough equivalent of the ; in many imperative programming languages.
2) what does two greater than symbols followed by equal sign mean?
x >>= y is like x >> y except it takes the result of x and applies to y, which has to be a function. Briefly put, getLine >>= \a -> action means "read a line, bind that value to variable a, and run action (which can depend from a).
I'd recommend a monad tutorial to fully understand these. You can start with a general tutorial such as LYAH.
Your code is more commonly written in do notation:
main = do
putStrLn "Enter 1st String:"
a <- getLine
read a
where the last line makes no sense: read returns a value but does not do any I/O, so we can not chain that to a sequence of I/O actions. This triggers a compiler error. If you know some imperative programming, think about the pseudocode
print("some message");
a = inputLine();
toInteger(a);
The last line makes no sense: it converts the string into an integer... and then does not use the result in any way.

About your second question: your main is not a valid monadic expression. When specialised to the IO monad, the bind and then operators have type
(>>=) :: IO a -> (a -> IO b) -> IO b
(>>) :: IO a -> IO b -> IO b
If you try to align the types of your main expression, you will identify the problem very quickly:
putStrLn "Enter 1st String:" >> getLine >>= \a -> read a
{ IO () } {IO String} {actual: Read t => String -> t }
{ IO String } {expected: String -> IO t} ??? }
The type expected for the second argument of >>= is String -> IO t, but read doesn't return an IO value.

Related

How to wrap char literal in IO monad in Haskell?

I know you're supposed to wrap up the operations you want to perform on a result in a monad rather than unwrap things from the monad.
What I can't find are any idiot-friendly examples of how to do that.
For example, I want to do something like this:
myFunction = do
c <- getChar
if (c == 'q')
then putStrLn "take action 1"
else putStrLn "take action 2"
But you can't compare a char literal to an IO Char directly.
GHCi version is 8.4.4.
Error Message:
[1 of 2] Compiling Lib ( /Users/jamesstrieter/hask-tink/src/Lib.hs, interpreted )
/Users/jamesstrieter/hask-tink/src/Lib.hs:66:18: error:
• Couldn't match expected type ‘IO char’ with actual type ‘Char’
• In the second argument of ‘(==)’, namely ‘'q'’
In the expression: x == 'q'
In an equation for ‘what2do’: what2do x = x == 'q'
• Relevant bindings include
x :: IO char
(bound at /Users/jamesstrieter/hask-tink/src/Lib.hs:66:9)
what2do :: IO char -> Bool
(bound at /Users/jamesstrieter/hask-tink/src/Lib.hs:66:1)
|
66 | what2do x = x == 'q'
| ^^^
Failed, no modules loaded.
The code you posted looks perfectly correct and functional.
do-notation is a way of working with value in monad.
c <- getChar within the do block binds c to the char inside the IO Char you get with getChar. You can compare c == 'q' just fine here because c is a plain char, not an IO Char.
To answer you direct question, you can use the return function to put a pure value into any monad, including IO, so return 'q' "wraps" the character literal 'q' into a monad. This isn't what you want in this case, the code you already have is what you are looking for.
But you can't compare a char literal to an IO Char directly.
Sure, but when you "bind" the result of the IO action it is no longer an IO Char but just a Char so that's why it works.
In more words:
Prelude> :t getChar
getChar :: IO Char
Prelude> c <- getChar
x
Prelude> :t c
c :: Char
One of the most important things to understand about the IO monad is that the expression m >>= f does not execute the action m, nor does it ever call the function f.
Instead, it just creates a new IO action that wraps both m and f, which, when executed, will finally execute m, extract the return value, and then execute the next action calculated on the spot by calling f with that value.
That's it. Your entire Haskell program is nothing but a DSL for building a single IO action that gets assigned to main, which the Haskell runtime will execute for you.
So when you write
-- Rewritten slightly for brevity
myFunction = do
c <- getChar
putStrLn (if (c == 'q')
then "take action 1"
else "take action 2")
this is desugared to
myFunction = getChar >>= (\c ->
putStrLn (if (c == 'q')
then "take action 1"
else "take action 2")
and what you are actually saying is "Build an IO action containing getChar and a function of type Char -> IO (), such that when this action is executed, it executes getChar and passes the resulting Char to the function to produce another IO action to be executed immediately."

How can I get this currying experiment to behave as expected?

I am writing a currying experiment to get a feel for how multiple statements in haskell are chained together to work one after another.
Here is what I got so far
testCurry :: IO ()
testCurry =
(\b ->
(\_ -> putStrLn b)
((\a ->
putStrLn a
) (show 2))
) (show 3)
testCurryExpected :: IO ()
testCurryExpected = do {
a <- return (show 2);
putStrLn a;
b <- return (show 3);
putStrLn b;
}
main :: IO ()
main =
putStrLn "expected: " >>
testCurryExpected >>
putStrLn "given: " >>
testCurry
I know it works if I do it this way:
testCurry :: IO ()
testCurry =
(\b ->
(\next -> next >> putStrLn b)
((\a ->
putStrLn a
) (show 2))
) (show 3)
testCurryExpected :: IO ()
testCurryExpected = do {
a <- return (show 2);
putStrLn a;
b <- return (show 3);
putStrLn b;
}
main :: IO ()
main =
putStrLn "expected: " >>
testCurryExpected >>
putStrLn "given: " >>
testCurry
But I don't know how to simulate the ">>"(then) behavior only using functions.
I know a >> b is defined in terms of a >>= \_ -> b, but I am not sure how >>= is defined in terms of IO a >>= IO b but don't know how to translate this into raw function composition.
Can somebody please help me get this experiment to work?
In short, I want to know if there is a way to do this without >> or >>= operators nor wrapping these operators.
(\a -> \b -> a >> b)(putStrLn "one")(putStrLn "two")
Note: For the sake of concept, I restrict myself to using anonymous functions of at most one argument.
Edit: I found a good-enough solution by creating my own Free representation of putStrLn called Free_PutStrLn that is free of interpretation; using Lists to construct the operation chain, then evaluate it myself later.
data Free_PutStrLn = Free_PutStrLn String deriving Show
eval :: [Free_PutStrLn] -> IO ()
eval a =
foldl (\a -> \b ->
let deconstruct (Free_PutStrLn str) = str in
a >> putStrLn (deconstruct b)
) (return ()) a
testCurry :: [Free_PutStrLn]
testCurry =
(\a ->
[Free_PutStrLn a] ++
((\b ->
[Free_PutStrLn b]
) (show 3))
)(show 2)
main =
putStrLn (show testCurry) >>
eval (testCurry)
JavaScript proof of concept:
// | suspends an object within a function context.
// | first argument is the object to suspend.
// | second argument is the function object into which to feed the suspended
// | argument(first).
// | third argument is where to feed the result of the first argument feeded into
// | second argument. use a => a as identity.
const pure = obj => fn => f => f(fn(obj));
// | the experiment
pure({'console': {
'log': str => new function log() {
this.str = str;
}
}})(free =>
pure(str => () => console.log(str))
(putStrLn =>
pure("hello")(a =>
[free.console.log(a)].concat (
pure("world")(b =>
[free.console.log(b)]
)(a => a))
)((result =>
pure(logObj => logObj.str)
(deconstruct =>
result.map(str => putStrLn(deconstruct(str)))
)(result =>
result.forEach(f => f())
)
)
)
)(a => a)
)(a => a)
But I don't know how to simulate the >> (then) behavior only using functions.
Well, you can't! >> is (in this case) about ordering side-effects. A Haskell function can never have a side effect†. Side effects can only happen in monadic actions, and can be thus ordered by monadic combinators including >>, but without a Monad‡ constraint the notion of “do this and also that” simply doesn't make any sense in Haskell. A Haskell function is not executed, it's merely a mathematical transformation whose result you may evaluate. That result may itself be an actual action with type e.g. IO (), and such an action can be executed and/or monadically chained with other actions. But this is actually somewhat orthogonal to the evaluation of the function that yielded this action.
So that's the answer: “How can I get this currying experiment to behave as expected?” You can't, you need to use one of the monadic combinators instead (or do notation, which is just syntactic sugar for the same).
To also tackle this question from a bit of a different angle: you do not “need monads” to express sequencing of side effects. I might for instance define a type that “specifies side-effects” by generating e.g. Python code which when executed has these effects:
newtype Effect = Effect { pythons :: [String] }
Here, you could then sequence effects by simply concatenating the instruction lists. Again though, this sequencing would not be accomplished by any kind of currying exercise but by boring list concatenation. The preferable interface for this is the monoid class:
import Data.Monoid
instance Monoid Effect where
mempty = Effect []
mappend (Effect e₀) (Effect e₁) = Effect $ e₀ ++ e₁
And then you could simply do:
hello :: Effect
hello = Effect ["print('hello')"] <> Effect ["print('world')"]
(<> is just a shorthand synonym for mappend. You could as well define a custom operator, say # instead to chain those actions, but if there's a standard class that supports some operation it's usually a good idea to employ that!)
Ok, perfectly fine sequencing, no monadic operators required.
But very clearly, just evaluating hello would not cause anything to be printed: it would merely give you some other source code. You'd actually need to feed these instructions to a Python interpreter to accomplish the side-effects.And in principle that's no different with the IO type: evaluating an IO action also never causes any side-effects, only linking it to main (or to the GHCi repl) does. How many lambdas you wrap the subexpressions in is completely irrelevant for this, because side-effect occurance has nothing to do with whether a function gets called anywhere! It only has to do with how the actions get linked to an actual “executor”, be that a Python interpreter or Haskell's own main.
If you now wonder why it has to be those whacky monads if the simpler Monoid also does the trick... the problem with Effect is that it has no such thing as a return value. You can perfectly well generate “pure output” actions this way that simply execute a predetermined Python program, but you can never get back any values from Python this way to use within Haskell to decide what should happen next. This is what monads allow you to do.
†Yes, never. Haskell does not include something called unsafePerformIO. Anybody who claims otherwise in the comments shall suffer nuclear retaliation.
‡To be precise, the weaker Applicative is sufficient.

How can monads determine ordering if their information is lost upon normalization?

If I understood correctly, a monad is just the implementation of a bind >>= and a return operator following certain rules which basically compose 2 functions of different return types together. So, for example, those are equivalent:
putStrLn "What is your name?"
>>= (\_ -> getLine)
>>= (\name -> putStrLn ("Welcome, " ++ name ++ "!"))
(bind (putStrLn "What is your name?")
(bind
(\_ -> getLine)
(\name -> putStrLn ("Welcome, " ++ name ++ "!"))))
But if we strongly normalize this expression, the final result will be just:
(putStrLn ("Welcome, " ++ getline ++ "!"))
The first statement (putStrLn "What is your name?") is completely lost. Also, getLine looks like a function with no arguments, which is nonsense. So how does this work, and what is the actual definition of the >>= and return functions?
Your logical misstep is that you assume certain reduction rules hold which do not. In particular, you appear to be using
f >>= (\x -> g x) ==== g f
If that held then, yes, monads would be pretty silly: (>>=) would just be flip ($). But it doesn't, in general, hold at all. In fact, the very reason it doesn't hold is what provides monads an opportunity to be interesting.
For a little bit of further exploration, here's the one monad where (>>=) == flip ($) (basically) holds.
newtype Identity a = Identity { unIdentity :: a }
To make our equations work out, we'll have to use that Identity a ~ a. This isn't strictly true, obviously, but let's pretend. In particular, Identity . unIdentity and unIdentity . Identity are both identities, no-ops, and we can freely apply Identity or unIdentity however we like to make types match
instance Functor Identity where
fmap f (Identity a) = Identity (f a)
instance Monad Identity where
return a = Identity a -- this is a no-op
ida >>= f = f (unIdentity ida)
Now, in particular, we want to examine
ida :: Identity a
f :: a -> b
ida >>= Identity . f :: Identity b
===
Identity (f (unIdentity ida)) :: Identity b
and if we throw away the Identity/unIdentity noise and thus produce the knowledge that ida = Identity a for some a
Identity (f (unIdentity ida)) :: Identity b
===
Identity (f a) :: Identity b
=== ~
f a :: b
So, while (>>=) == flip ($) forms a certain basis of intuition about (>>=)... in any circumstance more interesting than the Identity monad (and all other monads are) it doesn't hold exactly.
Seems to be a misunderstanding of how evaluation in IO proceeds in Haskell. If you look at the type signature for (>>=):
λ: :t (>>=)
(>>=) :: Monad m => m a -> (a -> m b) -> m b
It takes a monadic value parameterized by a type a, and a function which accepts a type of the same type and applies it inside the function body yielding a monadic value of type b.
The IO monad itself is a rather degenerate monad since it has special status in Haskell's implementation. A type of IO a stands for a potentially impure computation which, when performed, does some IO before returning a value of type a.
The first statement (putStrLn "What is your name?") is completely
lost.
The misunderstanding about this statement is that the value of putStrLn :: String -> IO () does in fact lose it's value in some sense, or more precisely it just yields the unit type () to the bound function after performing the IO action of printing a string to the outside world.
But if we strongly normalize this expression, the final result will be
just: (putStrLn ("Welcome, " ++ getline ++ "!"))
It's best to think of getLine :: IO String as being a computation yielding a value instead of a value itself. In this case as well the function getLine is not itself substituted in but the result of the computation it performs is, which behaves like you expect it to: getting a value from stdin and printing it back out.
It has been so long til I asked that question! The simple answer is that, no, the term I posted does not reduce to putStrLn ("Welcome, " ++ getline ++ "!"). Instead, its normal form will have the shape bind foo (\ _ -> bind bar (\ _ -> ...)), i.e., a chain of lambdas, which holds the ordering information I was worried about.
[...] what are the actual definitions for the (>>=) and return functions?
From section 6.1.7 (page 75) of the Haskell 2010 report:
The IO type serves as a tag for operations (actions) that interact with the outside world. The IO type is abstract: no constructors are visible to the user. IO is an instance of the Monad and Functor classes.
the crucial point being:
The IO type is abstract: no constructors are visible to the user.
There are no actual (written in idiomatic Haskell) definitions - it's the implementors' choice as to which model to use: state-threading, continuations, direct effects, etc. (This wasn't always the case - I provide more details here :-) We also benefit, as we're able to choose the most convenient model for the investigation being made.
So how does this work [...]?
I will choose the direct-effect model, based on examples from Philip Wadler's How to Declare an Imperative:
(* page 26, modified *)
type 'a io = oi -> 'a
infix >>=
val >>= : 'a io * ('a -> 'b io) -> 'b io
fun m >>= k = fn Oblige => let
val x = m Oblige
val y = k x Oblige
in
y
end
val return : 'a -> 'a io
fun return x = fn Oblige => x
val putc : char -> unit io
fun putc c = fn Oblige => putcML c
val getc : char io
val getc = fn Oblige => getcML ()
I'm using a new type:
datatype oi = Oblige
to reserve the unit type and its value () for the usual purpose of vacuous
results, for clarity.
(Yes - that's Standard ML: just imagine it's 1997, and you're writing a
prototype Haskell implementation ;-)
With the help of some extra definitions:
val gets : (char list) io
val putsl : char list -> unit io
that Haskell code sample, modified slightly:
putStrLn "What is your name?" >>=
(\_ -> getLine >>=
(\name -> putStrLn (greet name)))
greet :: String -> String
greet name = "Welcome, " ++ name ++ "!"
translates to:
putsl "What is your name?"
>>= (fn _ => gets
>>= (fn name => putsl (greet name))
where:
val greet : char list -> char list
fun greet name = List.concat (String.explode "Welcome, "::name::[#"!"])
All going well, the sample should simplify down to:
fun Oblige => let
val x = putsl "What is your name?" Oblige
val name = gets Oblige
val y = putsl (greet name) Oblige
in
y
end
Even though x isn't used it's still evaluated in Standard ML, which causes the prompt "What is your name?" to be displayed.
Now for a guess at the next question...Standard ML and Haskell are both functional languages - could all that oi stuff be transferred across to Haskell?
I was wrong? Meh; I'll answer it anyway - sort of; you can read about what I devised over here. If that was just too abominable to contemplate...well, here are those extra Standard ML definitions:
(* from pages 25-26, verbatim *)
val putcML : char -> unit
fun putcML c = TextIO.output1(TextIO.stdOut,c);
val getcML : unit -> char
fun getcML () = valOf(TextIO.input1(TextIO.stdIn));
(* Caution: work of SML novice... *)
val gets = fn Oblige => let
val c = getc Oblige
in
if c = #"\n" then
[]
else
let
val cs = gets Oblige
in
(c::cs)
end
end
fun putsl cs = fn Oblige => let
val _ = putsl cs Oblige
val _ = putc #"\n" Oblige
in
()
end
val puts : char list -> unit io
fun puts cs = fn Oblige => case cs of
[] => ()
| (c::cs) => let val _ = putc c Oblige in
puts cs Oblige

Convert a "do" notation with more than two actions to use the bind function

I know that the following "do" notation's "bind" function is equivalent to getLine >>= \line -> putStrLn
do line <- getLine
putStrLn line
But how is the following notation equivalent to bind function?
do line1 <- getLine
putStrLn "enter second line"
line2 <- getLine
return (line1,line2)
I take it you are trying to see how to bind the result of "putStrLn". The answer is in the type of putStrLn:
putStrLn :: String -> IO ()
Remember that "()" is the unit type, which has a single value (also written "()"). So you can bind this in exactly the same way. But since you don't use it you bind it to a "don't care" value:
getLine >>= \line1 ->
putStrLn "enter second line" >>= \_ ->
getline >>= \line2 ->
return (line1, line2)
As it happens, there is an operator already defined for ignoring the return value, ">>". So you could just rewrite this as
getLine >>= \line1 ->
putStrLn "enter second line" >>
getline >>= \line2 ->
return (line1, line2)
I'm not sure if you are also trying to understand how bind operators are daisy-chained. To see this, let me put the implicit brackets and extra indentation in the example above:
getLine >>= (\line1 ->
putStrLn "enter second line" >> (
getline >>= (\line2 ->
return (line1, line2))))
Each bind operator links the value to the left with a function to the right. That function consists of all the rest of the lines in the "do" clause. So the variable being bound through the lambda ("line1" in the first line) is in scope for the whole of the rest of the clause.
For this specific example you can actually avoid both do and >>= by using combinators from Control.Applicative:
module Main where
import Control.Applicative ((<$>), (<*>), (<*))
getInput :: IO (String, String)
getInput = (,) <$> getLine <* putStrLn "enter second line" <*> getLine
main = print =<< getInput
Which works as expected:
travis#sidmouth% ./Main
hello
enter second line
world
("hello","world")
It looks a little weird at first, but in my opinion the applicative style feels very natural once you're used to it.
I would strongly suggest you to read the chapter Desugaring of Do-blocks in the book Real-World haskell. It tells you, that you all are wrong. For a programmer, it's the natural way to use a lambda, but the do-block is implemented using functions which - if a pattern maching failuire occurs - will call the fail implementation of the according monad.
For instance, your case is like:
let f x =
putStrLn "enter second line" >>
let g y = return (x,y)
g _ = fail "Pattern mismatched"
in getLine >>= g
f _ = fail "Pattern mismatched"
in getLine >>= f
In a case like this, this may be completely irrelevant. But consider some expression that involves pattern-matching. Also, you can use this effect for some special stuff, eg, you can do something like this:
oddFunction :: Integral a => [a] -> [a]
oddFunctiond list = do
(True,y) <- zip (map odd list) list
return y
What will this function do? You can read this statement as a rule for working with the elements of the list. The first statement binds an element of the list to the var y, but only if y is odd. If y is even, a pattern matching failure occurs and fail will be called. In the monad instance for Lists, fail is simply []. Thus, the function strips all even elements from the list.
(I know, oddFunction = filter odd would do this better, but this is just an example)
getLine >>= \line1 ->
putStrLn "enter second line" >>
getLine >>= \line2 ->
return (line1, line2)
Generally foo <- bar becomes bar >>= \foo -> and baz becomes baz >> (unless it's the last line of the do-block, in which case it just stays baz).

Haskell Input Return Tuple

i wonder can a IO() function return tuple because i would like to get these out of this function as input for another function.
investinput :: IO()->([Char], Int)
investinput = do
putStrLn "Enter Username : "
username <- getLine
putStrLn "Enter Invest Amount : "
tempamount <- getLine
let amount = show tempamount
return (username, amount)
Please help.
Thanks.
IO in Haskell doesn't work like IO in the languages you're used to. All functions in Haskell must be pure: that is, if a function f is called with the argument x, there must be no difference between calling it once, twice, or a hundred times. Consider what this means for IO, though. Naïvely, getLine should have the type getLine :: String, or perhaps getLine :: () -> String. (() is the unit type, whose only value is (); it's sort of like a void type in a C-like language, but there is a single value of it.) But this would mean that every time you wrote getLine, it would have to return the same string, which is not what you want. This is the purpose of the IO type: to encapsulate actions. These actions are distinct from functions; they represent impure computation (though they themselves are pure). A value of type IO a represents an action which, when executed, returns a value of type a. Thus, getLine has type getLine :: IO String: every time the action is evaluated, a String is produced (by reading from the user). Similarly, putStr has type putStr :: String -> IO (); it is a function which takes a string and returns an action which, when run, returns no useful information… but, as a side effect, prints something to the screen.
You are attempting to write a function of type IO () -> ([Char], Int). This would be a function which took as input an action and returned a tuple, which is not what you want. You want an IO (String, Int)—an action which, when run, produces a tuple consisting of a string (which is a synonym for [Char]) and an integer. You're almost there with your current code, too! This is what you'll need instead:
investinput :: IO (String, Int)
investinput = do
putStrLn "Enter Username : "
username <- getLine
putStrLn "Enter Invest Amount : "
tempamount <- getLine
let amount = read tempamount
return (username, amount)
Notice that I've only made two changes (and removed a blank line). First, I've changed the type of the function, like I said above. Second, I changed show into read. The show function has the type Show a => a -> String: it is a function which takes anything which can be shown and produces a string representing it. You wanted read, which has the type Read a => String -> a: given a string, it parses it and returns some readable value.
The other thing you asked about is returning a tuple (String, Int) instead of an action IO (String, Int). There is no pure way to do this; in other words, there is no pure function IO a -> a. Why is this? Because IO a represents an impure action which depends on the real world. If we had such a function impossibleRunIO :: IO a -> a, then we would want it to be the case that impossibleRunIO getLine == impossibleRunIO getLine, since the function must be pure. But this is useless, as we would want impossibleRunIO to be able to actually interact with the real world! Thus, this pure function is impossible. Everything that enters IO can never leave. This is what return does: it is a function with, in this case1, the type return :: a -> IO a, which enables you to place pure values into IO. For any x, return x is an action which, when run, always produces x. This is why you have to end your do block with the return: username is a pure value you extracted from an action, and as such is only visible within the do block. You need to lift it into IO before the outside world can see it. The same is true of amount/tempamount.
And just for completeness's sake: there is some overarching theory behind this which ties it together. But it's not necessary at all for beginning Haskell programming. What I would recommend doing is structuring most of your code as pure functions which fold, spindle, and mutilate your data. Then construct a thin (as thin as possible) IO front layer which interacts with said functions. You'll be surprised how little IO you need!
1: It actually has a more general type, but that's not relevant for the moment.
Yeah, you're almost there but I think you want the signature:
investinput :: IO ([Char], Int)
... then from the calling function you can do something like:
main = do
(username, amount) <- investinput
....
I think you want to read tempamount rather than show though.
An IO function that produces a tuple would have type IO (a, b), in this case:
investinput :: IO ([Char], Int)
A signature of IO () -> ([Char], Int) would mean that the function takes a parameter of type IO () and produces a tuple from that, which is not what you want.
Generally there are no restrictions on the types an IO function (or a function in a different monad) can return, you can chose the types however you like.
The answer to your question about returning (String, Int) rather than IO (String, Int) is simple: you can't. Once you're in IO you're stuck there. That's part of what it means when people say that Haskell is a "pure" language.
What you want to do is similar to what you're already doing here with getLine. The type of getLine is IO String. When you write username <- getLine, you're in effect taking the String out of the IO String, but this is only possible because you're inside the do expression.
You can do exactly the same kind of thing with investinput as with getLine. Here's an example of how you could use investinput in your main function:
main = do
(name, amount) <- investinput
putStrLn $ name ++ " invested $" ++ show amount ++ "."
Since you mention liftM in a comment, here's a full working version that does the same thing using liftM and the reverse bind operator (=<<) instead of do notation:
import Control.Monad (liftM)
investinput :: IO (String, Int)
investinput = do
putStrLn "Enter Username : "
username <- getLine
putStrLn "Enter Invest Amount : "
amount <- liftM read getLine -- We can also use liftM to get rid of tempamount.
return (username, amount)
summary :: (String, Int) -> String
summary (name, amount) = name ++ " invested $" ++ show amount ++ "."
main = putStrLn =<< liftM summary investinput
This shows how you could use investinput with "another function which expects a tuple".

Resources