[Haskell-beginners] Trying to compile my first program that imports another program

Daniel Fischer daniel.is.fischer at web.de
Mon Apr 26 05:46:23 EDT 2010


Again, a lot has already been explained, so I have only a few additional 
remarks.

Am Montag 26 April 2010 03:07:36 schrieb Mitchell Kaplan:
> Hi,
>
> I created (with help) a function to test for prime numbers.  It worked
> well enough for now in ghci.
>
> ----------------
>
>     f x n y
>
>       | n>y = True
>       |
>       | rem x n == 0 = False
>       |
>       | otherwise = f x (n+1) y
>
>     primeQ x = f x 2 y
>
>       where
>
>       y = floor(sqrt(fromIntegral x))
>
> ---------------
>
> I then wanted to create object code so that I could import it.  It
> seemed that I had to precede the above with the 2 lines:
>
> ----------------
>
>     module Prime
>
>     where
>
> ----------------

If there is no explicit module declaration, the language standard 
prescribes the implicit declaration

module Main (main) where

which means your module is called Main and exports the single function (IO-
action) "main".

If you load the code in ghci (interpreted), it ignores the export list and 
makes all definitions from the top-level of the module available at the 
prompt. Since ghci is mostly used for testing code while it's written, that 
deviation from the standard is very useful.

If a module without module declaration doesn't define a function

main :: IO t

at the top level, it doesn't compile (implicitly, you say that you're 
exporting a function main, but you don't define it).

>
> I ran:
>
>    ghc -c prime.hs, and created prime.o and prime.hi.

It is generally better to use "ghc --make source.hs".
And the filename should match the module name (except the module Main can 
be in whatever file, test.hs, Main.hs, as you please - since that isn't 
imported, it's the root of the import chase, GHC doesn't need to 
automatically find it), so it should be Prime.hs (upper case P). That way, 
"ghc --make" can find it by itself and you don't need to list all needed 
object files on the command line.

>
> Next, I wanted to write a program to import and use this function.
>
> I wrote:
>
> ------------
>
>     module Main () where

That says Main doesn't export anything, but it should export at least main, 
so

module Main (main) where

>     import Prime
>
>     main = primeQ 123
>
> ------------
>
> I tried to compile this with:
>
>     ghc -o test Main.hs prime.o

If module Prime is defined in the file Prime.hs in the same directory (or 
somewhere you tell GHC to look), it becomes simply

ghc --make Main -o test

(or have the Main module in test.hs, then it's simply "ghc --make test").

>
> I got the following error:
>
>     Main.hs:5:0:
>         Couldn't match expected type 'IO t' against inferred type 'Bool'
>         In the expression: main
>         When checking the type of the function 'main'
>
> ----------------
>
> First I'd like a hint as to what I need to do to make this work.
>
> It's pretty obvious that I don't know what I'm doing with regard to
> types. Also, I have no idea if I have to name this module Main, but when
> I didn't the compiler complained about that.

You can call it something else, but then you have to tell the compiler 
explicitly what should be the 'main' function via "-main-is thing". E.g.

witch.hs
--------------------------------
module Hello where

hello :: String
hello = "All hail Macbeth!"

greet :: IO ()
greet = putStrLn hello
----------------------------------

$ ghc -main-is Hello.greet --make witch
[1 of 1] Compiling Hello            ( witch.hs, witch.o )
Linking witch ...
$ ./witch
All hail Macbeth!

If the module were named Main, it'd be "ghc -main-is greet ...", if the 
module name isn't Main, but your 'main' function is called "main", it'd be 
"ghc -main-is Hello --make ..."

>
> In the function that I think I had to re-write to make object code, I
> wound up with 2 where statements, which worries me.

Nested scopes. You always have one "where" defining the module scope, 
implicitly if you omit the module declaration. Then you can define local 
scopes in functions at the top-level of the module using another where (or 
a let), local-local scopes in local functions etc.

>
> I'd really appreciate any help in getting me unraveled.
>
>         Mitchell



More information about the Beginners mailing list