I start learning Haskell, and just tried a simple code, and it shows me some errors when I run
doubleMe :: Int -> Int
doubleMe x = x + x
main = do
doubleMe 2
ghc -c first.hs
The errors are:
$ ghc -c first.hs
first.hs:4:1: Couldn't match expected type
IO t0' with actual type
Int' In the expression: main When checking the type of the function `main'
While I use GCHi to debug, there were no issues to load doubleMe
function first, and call it later. Any help would be appreciated.
It doesn't work because anything using do notation must return a monad. GHCI does some things to make it more useful but it doesn't exactly work like code compiled by GHC.
print :: Show a => a -> IO ()
print
takes a value that is an instance ofShow
and returns an emptyIO
action. This is most likely what you want to do.main = print (doubleMe 2)
Should work as probably what you want to do. You don't have the type of the
main
function defined but in haskell in has to have the typemain :: IO ()
. Looking at the type ofdoubleMe
you can probably see why your code doesn't work.There are some things happening behind the scenes that make it hard to understand this error message. Here's the reasoning:
Main
.main
in moduleMain
has to have typeIO something
.main
you wrote has typeInt
.IO something
is not the same asInt
, no matter what we choose for thesomething
.GHC only reports the last step.
If you want to print the
Int
, you can useprint
to construct an IO action:This problem doesn't show up in ghci, because there, you can enter expressions of whatever type you want. If the type is
IO something
, ghci will execute the IO action for you. (Example:readFile "foo.txt"
). If the type is notIO something
, ghci will add a call toprint
and then execute that IO action (Example:['a' .. 'z']
).In a source file, you have to add the call to
print
yourself if you want it or need it.main
must be a value of typeIO a
, anddoubleMe 2
has typeInt
. You probably wanted toprint
the value:Your
main
function takes nothing and returns an integer. You probably wantwhich instead outputs 4 to STDOUT.
Congratulations, you have run into Monads.
main
is an IO monad and must act as such. IO monads do not returnInt
s. Instead an IO Monad is an IO action, returned byprint
and executed at runtime.Every function in Haskell returns a value of a certain type.
In this case, the
doubleMe
function returns a value of theInt
type. When you load a file from the ghci interpreter, it loads all the functions from the file and makes them available to you.The
main
function is a slightly special function, much like in other languages. It defines the entry point of a Haskell program. However, since it is just another Haskell function it too must return a value of a particular type. Themain
function is constrained to return a value of theIO
type, most commonlyIO ()
.IO
itself is quite special too, belonging to a class of types called monads. You can read up on theIO
monad here.Let us now return to your code:
Ignore the
do
syntax for a moment. You're basically telling the compiler that themain
function returnsdoubleMe 2
which is of typeInt
. This won't fly.main
has to return a value ofIO
type. In which case, you can use thereturn
function to convert anInt
value into anIO Int
value. (return
functions are functions that all monadic types must have. Very simply put, it converts a value of any type, into a monadic value.)So this becomes:
This is perfectly valid code, and will compile. However, once you run the program, you'll notice that it doesn't do anything. That's because the program returns the value 4. In fact, you can write it without the do, and it becomes:
This will work too.
Let us assume however, that you want to print out the value. This is where
IO
really comes in. Printing to a screen is anIO
action.A
do
expression allows you to chain a set ofIO
actions. So your program will still return the value4
but it will first evaluate the expressionprint (doubleMe 2)
. As expected, that actually results in printing the valuedoubleMe 2
. Examine theprint
function in ghci.The print function works on a value of any type that can be shown and it results in an
IO
action (printing to the screen) but returns nothing()
.All of these examples work, and will hopefully make things a little clear. (Look at the type signatures for
main
).