Search code examples
haskellghcighc-mod

Why does ghci not use relative paths?


If I have a project structured like this:

project/
  src/
    Foo.hs
    Bar.hs

With files Foo.hs:

module Foo where  

foo :: String
foo = "foo"

and Bar.hs:

module Bar where

import Foo 

bar :: String
bar = foo ++ "bar"

If my current directory is src, and I enter ghci and run :l Bar.hs, I get the expected output:

[1 of 2] Compiling Foo              ( Foo.hs, interpreted )
[2 of 2] Compiling Bar              ( Bar.hs, interpreted )
Ok, modules loaded: Bar, Foo.

But if I move up to the project directory (which is where I'd prefer to stay and run vim/ghci/whatever), and try :l src/Bar.hs, I get:

src/Bar.hs:3:8:
    Could not find module ‘Foo’
    Use -v to see a list of the files searched for.
Failed, modules loaded: none.

Why does ghc not search for Foo in the same directory as Bar? Can I make it do so? And can I propagate that change up to ghc-mod and then to ghcmod.vim? Because I get errors about can't find module when I'm running my syntax checker or ghc-mod type checker in vim.

I'm running ghc 7.10.1.


Solution

  • The flag you're looking for is -i<dir>:

    % ghci --help
    Usage:
    
        ghci [command-line-options-and-input-files]
    
    ...
    
    In addition, ghci accepts most of the command-line options that plain
    GHC does.  Some of the options that are commonly used are:
    
        -i<dir>         Search for imported modules in the directory <dir>.
    

    For example

    % ls src
    Bar.hs Foo.hs
    % ghci -isrc
    GHCi, version 7.8.2: http://www.haskell.org/ghc/  :? for help
    Loading package ghc-prim ... linking ... done.
    Loading package integer-gmp ... linking ... done.
    Loading package base ... linking ... done.
    λ :l Foo
    [1 of 1] Compiling Foo              ( src/Foo.hs, interpreted )
    Ok, modules loaded: Foo.
    λ :l Bar
    [1 of 2] Compiling Foo              ( src/Foo.hs, interpreted )
    [2 of 2] Compiling Bar              ( src/Bar.hs, interpreted )
    Ok, modules loaded: Foo, Bar.
    

    You can also pass ghc-mod the -i<dir> flag from within ghcmod.vim

    If you'd like to give GHC options, set g:ghcmod_ghc_options.

    let g:ghcmod_ghc_options = ['-idir1', '-idir2']
    

    Also, there's buffer-local version b:ghcmod_ghc_options.

    autocmd BufRead,BufNewFile ~/.xmonad/* call s:add_xmonad_path()
    function! s:add_xmonad_path()
      if !exists('b:ghcmod_ghc_options')
        let b:ghcmod_ghc_options = []
      endif
      call add(b:ghcmod_ghc_options, '-i' . expand('~/.xmonad/lib'))
    endfunction