Simple haskell code can't compile

2019-09-01 01:36发布

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 typeInt' 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.

标签: haskell
5条回答
兄弟一词,经得起流年.
2楼-- · 2019-09-01 01:38

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.

查看更多
乱世女痞
3楼-- · 2019-09-01 01:44

There are some things happening behind the scenes that make it hard to understand this error message. Here's the reasoning:

  1. Your file doesn't have a module name, so ghc assumes that you are defining module Main.
  2. The name main in module Main has to have type IO something.
  3. But the main you wrote has type Int.
  4. IO something is not the same as Int, no matter what we choose for the something.

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.

查看更多
看我几分像从前
4楼-- · 2019-09-01 01:46

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)
查看更多
Juvenile、少年°
5楼-- · 2019-09-01 01:51

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 Ints. Instead an IO Monad is an IO action, returned by print and executed at runtime.

查看更多
地球回转人心会变
6楼-- · 2019-09-01 01:54

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"
查看更多
登录 后发表回答