Loading Haskell Modules that have dependencies - haskell

I'm unsure what my issue is here. I have a trio of modules A.hs, B.hs, and C.hs. All are located at C:\..path...\folder and modules B and C both import from A.
That is, both modules B and C contain the line import A
I can :l C:\..path..\folder\A.hs in gchi and play with its contents; however, ghci gives the following error when I try to :l C:\..path..\folder\B.hs or :l C:\..path..\folder\C.hs
Could not find module `A'
Use -v to see a list of the files searched for.
Failed, modules loaded: none.
Which I find odd because I had no trouble compiling B.hs to B.exe and running the executable. How can I compile and run a module that I can't load into ghci? Or, why would an import succeed at compile time but fail in loading; especially when that very module being imported is itself load-able?

By default, ghci searches only in the current directory for imported modules. To start with, the current directory is the one used to launch ghci; but it can be changed from within ghci with the :cd command. Thus, you could
> :cd C:\...path...\folder
> :l B.hs
and this should find both B.hs and A.hs in what is now the current directory. Alternately (and especially if you have modules in multiple directories) you can launch ghci with the -i command line option to add directories to its module search path. For example, in your command prompt you might
% ghci -iC:\...path...\folder
> :l B.hs
which will instruct ghci to include C:\...path...\folder in its search path, and therefore find B.hs and A.hs there even if it is not the current directory.

Related

Error: module ‘main:Course’ is defined in multiple files: src/Course.hs

I'm trying to start working on https://github.com/system-f/fp-course. After running stack ghci, it finishes with:
...
[51 of 51] Compiling Test.Loader ( src/Test/Loader.hs, interpreted )
Ok, 51 modules loaded.
Loaded GHCi configuration from /home/lpied/haskell/fp-course/.ghci
<no location info>: error:
module ‘main:Course’ is defined in multiple files: src/Course.hs
src/Course.hs
Failed, 51 modules loaded.
Loaded GHCi configuration from /tmp/haskell-stack-ghci/75d10d48/ghci-script
Any idea why it's complaining that the module is defined in the same file (src/Course.hs)?
Can you try using stack exec ghci instead? stack ghci is probably recognizing the src directory and adding -isrc to the ghci command line, and then the .ghci file in the course root directory is also adding -isrc to the ghci command line. GHC probably doesn't de-duplicate its search path, so it acts like you have two separate directories which both happen to be named src.

Why can't the ghci find the hs file that I am trying to compile?

I'm learning Haskell for the first time and I can't see to understand why the ghci can't find the file I'm trying to compile. Especially since, I saved the file. This is my file,
import System.IO
trueAndFalse = True && False
Now this is what I ran in the compiler,
<no location info>: error: can't find file: tut-1.hs
Failed, no modules loaded.
The "Failed, no modules loaded." makes me think you're talking about ghci. If so, you can find out where ghci is looking for files with :show paths. Here's what it looks like when I try:
> :show paths
current working directory:
/home/<my username>
module import search paths:
.
The module import search paths tells you what directories it's looking in. A lone . in that list refers to the current working directory. So, for me, if I wanted a file to be easily accessible from that ghci instance, I would have to save it in /home/<my username>.
Of course there are ways of changing all of these pieces -- which paths are in the import search path, which directory is the current working directory, and so forth -- but this should get you going for simple usage.
And, by the way, a note on terminology: the GHC tool suite comes with both a compiler and an interpreter. The compiler's executable is ghc, and the interpreter's executable is ghci. Knowing about that distinction may help you avoid confusion in future conversations!

Can GHCI's :add command accept a path that is relative to one's home directory?

This is the GHC manual documentation for :add:
:add[*] ⟨module⟩
Add ⟨module⟩(s) to the current target set, and perform a reload. Normally pre-compiled code for the module will be loaded if available, or otherwise the module will be compiled to byte-code. Using the * prefix forces the module to be loaded as byte-code.
I can tell from experimentation that ⟨module⟩ doesn't actually have to be the name of a module; it can also be a file path. And if it is not an absolute path, it seems to be resolved relative to the current directory from which the REPL was launched.
Is it possible to refer :add a path that is relative to one's home directory?
For example, I'd like to include $HOME/.ghci/imports.hs from my global GHCI config. (For the motivation behind this, see Can a GHCI config file use CPP macros?)
I've tried the obvious
:add $HOME/.ghc/imports.hs
but it doesn't work:
<no location info>: error: can't find file: $HOME/.ghc/imports.hs
Failed, modules loaded: none.
Use ~ instead of $HOME.
λ :add ~/Documents/Code/Haskell/Ackermann
[1 of 1] Compiling Ackermann ( /Users/rampion/Documents/Code/Haskell/Ackermann.hs, interpreted )
Ok, modules loaded: Ackermann.

Getting Source Files to Run in Haskell Programming (WinGHCi)

I can't figure out how to get WinGHCi to load and compile my .hs file.
I have a file, C:\Users\Haskell\Source\hello.hs, that only contains the following line:
main = putStrLn "Hello, world!"
If, at the Prelude> prompt, I run
:cd C:\Users\Haskell\Source\
nothing happens, which I'm assuming means the command was successful. However, when I try to run
:load hello.hs
I get a "[1 of 1] Compiling Main. Ok, modules loaded: Main" message. My prompt then changes from "Prelude" to "*Main" and I type:
ghc -o hello hello.hs
After that, I will get a series of errors talking about how ghc, o, hello, hello, and hs are "Not in scope."
I am in the correct directory. Why won't my program run?
One of my problems is that I'm unable to navigate the directories. I know that :!dir lists the files, and I am in the right directory, but :load hello.hs still doesn't work and I keep getting the scope error.
Any help would be appreciated.
EDIT: A user pointed out that if I have gotten to the *Main prompt, then my program has been loaded and compiled and I do not need to run the ghc command. If that is the case, how would I run it? Haskell.org states that, "You can then run the executable (./hello on Unix systems, hello.exe on Windows)," but an exe has not been created.
I find it easier to first navigate to the directory then invoke ghci. Once in Prelude you can use :l and the file name.
Or, you could load ghci then use :l and use the fully qualified path for the file.
Edit:
After reading your edits, it is clear you are getting your code compiled fine. Once it says it has compiled, there is no reason to try and do so again with ghc (I don't think you can do that from within ghci anyhow).
Now that it is compiled, you can use any of the code and data types defined there in. So to use your main function, just type in main at the *Main> prompt.

Haskell loading modules problem in emacs

I have 2 Haskell modules in emacs: Mod1.hs and Mod2.hs
Mod1.hs:
module Mod1 where
...
In the second module i try to import first module:
import Mod1
But get error:
Could not find module `Mod1':
Use -v to see a list of the files searched for.
Failed, modules loaded: none.
In emacs i use standard Haskell-mode. Mod1.hs and Mod2.hs files in the same directory.
How can i fix it?
Thank you.
You need to set the search-path of the interpreter running in Emacs to include the directory with your files. In the GHCi interpreter do:
Prelude> :cd /home/you/projects/yourproject
Replacing /home/you/projects/yourproject with the path to your .hs files of course. (Do :!pwd in the interpreter to print the current path.) You should then be able to do:
Prelude> :l Mod2
(Or C-c C-l in the Mod2.hs buffer.) See the GHC user guide for details.
This may help, if you put it in your .emacs:
(setq inferior-haskell-find-project-root nil)
It tells ghci not to move from the current directory.

Resources