问题
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.
回答1:
Every function in Haskell returns a value of a certain type.
In this case, the doubleMe
function returns a value of the Int
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. The main
function is constrained to return a value of the IO
type, most commonly IO ()
.
IO
itself is quite special too, belonging to a class of types called monads. You can read up on the IO
monad here.
Let us now return to your code:
main = do
doubleMe 2
Ignore the do
syntax for a moment. You're basically telling the compiler that the main
function returns doubleMe 2
which is of type Int
. This won't fly. main
has to return a value of IO
type. In which case, you can use the return
function to convert an Int
value into an IO 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:
main = do
return (doubleMe 2)
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:
main = return (doubleMe 2)
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 an IO
action.
main = do
print (doubleMe 2)
return (doubleMe 2)
A do
expression allows you to chain a set of IO
actions. So your program will still return the value 4
but it will first evaluate the expression print (doubleMe 2)
. As expected, that actually results in printing the value doubleMe 2
.
Examine the print
function in ghci.
> :t print
print :: Show a => a -> IO ()
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
).
-- main :: IO Int
main = return (doubleMe 2)
-- main :: IO Int
main = do
print (doubleMe 2)
return (doubleMe 2)
-- main :: IO ()
main = do
print (doubleMe 2)
return ()
-- main :: IO ()
main = do
print (doubleMe 2)
-- main :: IO ()
main = print (doubleMe 2)
-- main :: IO ()
main = do
print "Hello"
print (doubleMe 2)
return ()
-- main :: IO String
main = do
print "Hello"
print (doubleMe 2)
return "Hello"
回答2:
main
must be a value of type IO a
, and doubleMe 2
has type Int
. You probably wanted to print
the value:
main = print (doubleMe 2)
回答3:
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 of Show
and returns an empty IO
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 type main :: IO ()
. Looking at the type of doubleMe
you can probably see why your code doesn't work.
回答4:
Your main
function takes nothing and returns an integer. You probably want
doubleMe :: Int -> Int
doubleMe x = x + x
main = do
print $ doubleMe 2
which 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 return Int
s. Instead an IO Monad is an IO action, returned by print
and executed at runtime.
回答5:
There are some things happening behind the scenes that make it hard to understand this error message. Here's the reasoning:
- Your file doesn't have a module name, so ghc assumes that you are defining module
Main
. - The name
main
in moduleMain
has to have typeIO something
. - But the
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 use print
to construct an IO action:
main = do
print (doubleMe 2)
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 not IO something
, ghci will add a call to print
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.
来源:https://stackoverflow.com/questions/23049409/simple-haskell-code-cant-compile