PinkiePie-Z
PinkiePie-Z

Reputation: 553

What is the difference between IO () and IO?

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

Answers (4)

lynn
lynn

Reputation: 10814

IO Int means: this is an IO action that returns an Int.

IO () means: this is an IO action that doesn't return any meaningful result. (like main.)

Upvotes: 1

Ben
Ben

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

Gabriella Gonzalez
Gabriella Gonzalez

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

Matt S
Matt S

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

Related Questions