Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my Haskell code saying 'variable not in scope: main'?

When I type the following in the interactive shell of Haskell on the repl.it website, it works perfectly.

let squareMe x = x * x
let myFruit = ["banana", "apple", "kiwi", "orange"]

But when I type it into a source file and click 'Run' I get the error:

<interactive>:3:1: error:
    • Variable not in scope: main
    • Perhaps you meant ‘min’ (imported from Prelude)

I've been trying to understand this error and come up with a solution for a couple of hours now and am no nearer to finding a solution or understanding what the error means.

like image 814
branty1970 Avatar asked Oct 03 '17 14:10

branty1970


2 Answers

The Haskell REPL (GHCi) and actual Haskell programs are considerably different.

The reasons for this difference is the goal of the two formats. Firstly, GHCi is a testing area, not a code-running area. However, Haskell source files are meant to run a certain process, which is named main. When you run a source file, the Haskell compiler (usually GHC) looks for the IO action called main, and tries to run it. In this case, there was no main, so it failed.

Secondly, what you typed is not a valid Haskell program, those are declarations that would be fine in GHCi, but not in Haskell source. This would be correct in a source file:

squareMe x = x * x

myFruit = ["banana", "apple", "kiwi", "orange"]

Note the lack of let; Haskell source files don't use it to declare things.

Note that on repl.it, this will still complain that main is missing, but you can then refer to squareMe and myFruit in the REPL without worry. In other words, the error will still appear, but it doesn't matter, because you can use whatever you wrote in the file nonetheless.

If you wanted to suppress the warning, you could write the lines:

main :: IO ()    -- This says that main is an IO action.
main = return () -- This tells main to do nothing.

There are many things you could have the program do instead of this. Here are a couple of examples:

  • main = putStrLn "No errors!" Will print No errors! when you run it.
  • main = print myFruit Will print ["banana", "apple", "kiwi", "orange"] when you run it.

Please note that this answer applies mostly to the site repl.it specifically, though in general this is how Haskell programs are structured.

like image 94
AJF Avatar answered Nov 06 '22 04:11

AJF


If you compile a Haskell source there needs to be a main symbol as entry point, just like when compiling e.g. a C program. Also in a compiled file you must skip the lets. E.g.

squareMe x = x * x

main = putStrLn . show $ squareMe 4
like image 9
mschmidt Avatar answered Nov 06 '22 03:11

mschmidt