4
votes

I've done a fair bit of programming in haskell using GHCI however our next assignment requires us to use just GHC to compile and test our code.

Because of how ghci works compared to ghc you apparently need to use a main function and the ghc looks for this function in your code.

My question is, if Haskell promotes type safety and no side-effects unless within an IO action, why does the main part of any haskell program have to be an IO action?

Forgive me if I'm not understanding something fundamental, I just couldn't find any resources which ultimately explains this.

3
Simon Peyton-Jones on IO: " I/O is the raison d’etre of every program. — a program that had no observable effect whatsoever (no input, no output) would not be very useful "chi
Note that whenever you are in GHCi and do something like 3<Enter> you are in essence writing, and then running, the program main = print 3.Luc Danton
Note that, while this question is very simple, it's one of those that's so simple that nobody has actually explained it anywhere.MathematicalOrchid

3 Answers

13
votes

If your main function is not an IO action, then all it can do is produce a result. Since Haskell is lazy, this (usually) means that it just produces a promise that the computation will be performed, but it won't compute it until it needs to be used. Since the usual way to ensure something is computed is to print that value out, or send it over a network, save it to disk, or use it for some other kind of IO, your result won't be computed and the program would simply exit. Imagine a fake program like

main :: Int
main = 1 + 1

Suppose you could compile and run this, what would you expect to happen? Nothing gets printed, nothing is asking for the result of main, all that Haskell can do with this is create the promise that 1 + 1 will be computed at some point then exit the program. Basically, you can't do anything interesting at the top level without IO, and since we want programs to do interesting things we need our top level to be an IO action.

4
votes

Put simply, running a program is a side-effect. This is why the top-level function is an I/O action.

An ideal Haskell program is a large chunk of pure code with a thin I/O "skin" around it.

2
votes

I think it's pretty straightforward - ultimately, you need every program to do IO at the top level - otherwise how would you know if it did anything at all, or - how useful would it be? So you must have either console I/O, network I/O, disk I/O, or something similar. I don't see how you could get around that.