Reputation: 553
There are two different ways of using IO
in haskell programs, for example:
main :: IO ()
-- and
readLine :: IO Int
What is the difference between these two?
Upvotes: 2
Views: 527
Reputation: 10814
IO Int
means: this is an IO action that return
s an Int.
IO ()
means: this is an IO action that doesn't return any meaningful result. (like main
.)
Upvotes: 1
Reputation: 71590
IO ()
is the type of an action that can be executed to extract a value of type ()
. There is only one (non-bottom) value of type ()
, which is also spelled ()
(you tell them apart by knowing whether you're looking at a type expression or a value expression, just as names starting with an uppercase letter are either type constructors or data constructors, depending on whether you're looking at a type expression or a value expression). Since there is only one (non-bottom) value, the value tells you absolutely nothing (strictly speaking it does at least tell you that the computation did terminate successfully, but that's all). So IO ()
is usually used as the type of IO actions that we're only interested in for their side-effects.
putStrLn "Hello World"
is an example of a value of type IO ()
. It doesn't compute anything at all interesting; what is the value resulting from having written a string to the terminal? Getting the ()
when it's executed only tells us that it did indeed execute.
IO Int
is the type of an action that can be executed to extract a value of type Int
. As with all IO actions, what exactly it does can have effects on and be affected by the world outside the program; Haskell knows nothing about them. But it does know that executing the action will result in a Haskell value of type Int
, regardless of whatever else it might do.
readLn :: IO Int
is an example of a value of type IO Int
(the type annotation is necessary as a standalone expression to avoid ambiguity; in a wider context where you actually use the value extracted from readLn
for some Int
-specific operations you could probably leave it off). Unlike writing a string to the terminal, reading a string from the terminal and converting it to an Int
does result in a value.
More generally IO
is a type constructor that can be applied to any type; IO a
is the type of an execution that could be executed and would result in a value of type a
. Both of the above are just examples of this; neither is handled specially. ()
is a perfectly ordinary type, and ()
is a perfectly ordinary value of that type, but because such values don't convey any information (other than "this computation successfully terminated") you don't normally see ()
on its own; it tends to be used only with type constructors applied, such as in IO ()
, for values where we care only about the structure added by the type constructor, not about the values "inside" it.
Upvotes: 1
Reputation: 35099
The only difference is their return value. main
returns a value of type ()
and your readLine
returns an Int
. Perhaps this example will help:
main = do
x <- putStrLn "Test"
print x
When you run it, it outputs:
>>> main
Test
()
The print statement prints a ()
because that is the return value of putStrLn
:
putStrLn :: String -> IO ()
The reason you normally don't bind the return value of something like putStrLn
is that there is no information gained from doing so, since it always returns ()
no matter what.
Upvotes: 5
Reputation: 376
IO ()
and IO Int
are fundamentally very similar. Int
and ()
are both types in Haskell. ()
is special only in the sense that it has only one value ( also denoted by ()
), so we're never really interested in it.
Upvotes: 6