Missing main [GHC-67120]

GHC expects the Main module to define a function called main which it can use as the entry point of your program.

This error can also occur in unnamed modules, because GHC will default to the module name Main for such modules.

If you just want GHC to produce an object file without an entry point, then you can give your module a name other than Main by putting a module header at the top of your file (below language pragmas and compiler options), for example as follows:

module Foo where

The conventions around main are defined in the second paragraph of Chapter 5 of The Haskell 2010 Report,

A Haskell program is a collection of modules, one of which, by convention, must be called Main and must export the value main. The value of the program is the value of the identifier main in module Main, which must be a computation of type IO t for some type t (see Chapter 7). When the program is executed, the computation main is performed, and its result (of type t) is discarded.

Example error text

example1/before/Lib.hs:1:1: error: [GHC-67120]
    The IO action ‘main’ is not defined in module ‘Main’
  |
1 | factorial :: Int -> Int
  | ^
example2/before/Main.hs:1:1: error: [GHC-67120]
    The IO action ‘main’ is not defined in module ‘Main’
  |
1 | notMain :: IO ()
  | ^

Examples

Missing module header

In this example, the file Lib.hs is intended to contain a module called Lib which is not supposed to be the main module. However, the file is missing a module header, so GHC defaults to the module name Main and expects the main function. Adding an explicit module header with the name Lib solves this issue.

Lib.hs
Before
factorial :: Int -> Int
factorial n = product [1..n]
After
module Lib where

factorial :: Int -> Int
factorial n = product [1..n]
main has wrong name

In this example, the notMain value is the intended entry point of the program, but it is not called main so GHC does not find it. Renaming notMain to main solves the issue.

Main.hs
Before
notMain :: IO ()
notMain = putStrLn "Hello, World!"
After
main :: IO ()
main = putStrLn "Hello, World!"