I am trying to teach myself Haskell from the book Learn You A Haskell for Great Good. I got up to the last section of chapter 7 (Modules), where it tells how to create your own module. I did a copy and paste of the Geometry module given in the book at the beginning of the section. The name of the file is Geometry.hs, as the book suggested, and the file is in the bin directory for ghci, which is where I previously was able to successfully do a load using :l for another .hs file.
When I type the following command in GHCi
import Geometry
I get the following error:
Could not find module 'Geometry' It is not a module in the current
program or in any known package
I must be doing something that is obviously wrong, but I can't figure out what it is.
When you use import ModuleName in GHCi, it works (mostly) in the same way import Data.List works: GHC checks your local package database for the module, loads it, and brings its (exported) contents into scope.
However, Geometry isn't a module of a package installed with ghc-pkg. Therefore, GHC doesn't know that a module Geometry exists at all. Neither does it interactive variant GHCi.
But if you :load a program, things change. GHC will take its used modules into account:
-- Foo.hs
module Foo where
foo :: IO ()
foo = putStrLn "Hello from foo!"
-- Main.hs
module Main where
import Foo (foo)
main :: IO ()
main = foo
$ cd /path/to/your/files
$ ghci
GHCi, version 7.10.2: http://www.haskell.org/ghc/ :? for help
Prelude> import Foo
<no location info>:
Could not find module ‘Foo’
It is not a module in the current program, or in any known package.
Prelude> :l Main.hs
[1 of 2] Compiling Foo ( Foo.hs, interpreted )
[2 of 2] Compiling Main ( Main.hs, interpreted )
Ok, modules loaded: Main, Foo.
*Main> :l Main.hs
*Main> foo
Hello from foo!
*Main> import Foo
*Main Foo> -- module now loaded
As you can see, importing Foo first failed. However, after we've actually loaded the program that uses Foo, we were able to use import Foo in GHCi.
So if you want to use import in GHCi, make sure that GHC can find your module, either by including it in a wrapper or installing it. If you just want to load the module itself, use :load.
TLDR: the Learn you a Haskell book fails to mention that you have to :load the Geometry.hs file first. Then :m to go back to Prelude and then import Geometry works.
It is now also possible to add the lib flag when installing packages, i.e. to run cabal install --lib packagename and then to import the corresponding package directly in GHCi. In the present case, for example cabal install --lib hgeometry would facilitate importing modules from this geometry package.
Related
I have a haskell package called prime-tools. When I use stack ghci inside the package directory, I expect it to open up an interactive ghci and automatically import prime-tools. Instead, I find that it loads all of the modules declared in the .cabal file.
For example, here is the extract from my .cabal file showing which modules are declared:
library
-- Modules exported by the library.
exposed-modules: PrimeTools.MathStuff, PrimeTools.Factors, PrimeTools.PQTrials, PrimeTools.Main, PrimeTools.Base, PrimeTools.Lucas
-- Modules included in this library but not exported.
other-modules: PrimeTools.Extras
And this is what happens as I receive the ghci> prompt after running stack ghci in the project folder:
Ok, modules loaded: PrimeTools.MathStuff, PrimeTools.Factors, PrimeTools.PQTrials, PrimeTools.Main, PrimeTools.Base, PrimeTools.Lucas, PrimeTools.Extras.
ghci>
The problem with loading the modules instead of import prime-tools is that I can now use all functions defined in all modules whether or not they are exported.
An example of the issues arising from this distinction: there are two modules in package prime-tools which have implementations of a function called pfactor. One of them is exported, and intended to be used by the end user of the package, while the other is for internal use only and not exported.
Before someone comments, there is good reason to have two implementations of pfactor, but it's not relevant to my question.
My question: how can I use stack to automatically start up a ghci environment with the local version of ghc and import the package whose folder I run the command in?
My desired behaviour would be equivalent to running the following sequence of commands:
stack ghci
ghci> :module -PrimeTools.MathStuff
ghci> :module -PrimeTools.Factors
ghci> :module -PrimeTools.PQTrials
ghci> :module -PrimeTools.Main
ghci> :module -PrimeTools.Base
ghci> :module -PrimeTools.Lucas
ghci> :module -PrimeTools.Extras
ghci> import PrimeTools.MathStuff
ghci> import PrimeTools.Factors
ghci> import PrimeTools.PQTrials
ghci> import PrimeTools.Main
ghci> import PrimeTools.Base
ghci> import PrimeTools.Lucas
The key here is that I want to import the exposed-modules declared in the .cabal file and not to load any modules. I don't mind if the other-modules are also imported, though. Is there a way I can do this using stack without having to run this long sequence of commands every time?
A reasonable workaround is defining a custom GHCi macro for importing your modules the way you want it. Create a .ghci file in your project root along these lines:
:{
:def deload (\_ -> return
":module -PrimeTools.MathStuff\n\
\import PrimeTools.MathStuff"
)
:}
With this, the :deload command in GHCi will remove from scope and then re-import PrimeTools.MathStuff -- you can add as many modules as you want to the list. Though I have written this using multiline string syntax, you can have any String -> IO String expression within the parentheses, so feel free to spell or extend it however you see fit.
I made a mistake in another question that could have been solved by viewing
:t myfunctionofinterest
for a function I was using in a library.
However, when I am in my project root, and run
$ stack ghci
And my Main.hs has:
import MyLib
And my module does:
module MyLib {
bunchOfFunctions -- but not myfunctionofinterest
} where
import SomeDB.ModuleThatExposes -- myfunctionofinterest
myfunc :: IO ()
myfunc = do
myfunctionofinterest a b c -- place where I misuse myfunctionofinterest and could have used :t on it to see it had 3 args
I can't :t myfunctionofinterest in the main since it's not exposed, nor does Import MyLib.myfunctionofinterest explicitly
help, since it was something defined in an import. While I know I could expose it then check it, :a to compile, and then edit the lib to hide it again, is there anything that allows that more quickly and directly?
This seems like it must be a common pattern. What do you do when you need to check the type of something used in a library as you develop?
Quoting the GHCi docs:
The :module command provides a way to do two things that cannot be done with ordinary import declarations:
:module supports the * modifier on modules, which opens the full top-level scope of a module, rather than just its exports.
The additional * makes GHCi load the bytecode version of the module. This will not be as performant, but you'll get access to unexported bindings.
Example:
λ> :m *MyLib
λ> :t myfunctionofinterest
If you get
module 'MyLib' is not interpreted; try ':add *MyLib' first
you may have to do :load first (the advice about :add doesn't always do the trick):
λ> :l *MyLib
λ> :m *MyLib
λ> :t myfunctionofinterest
I put this in ~/Desktop/Shapes.hs:
module Shapes
( Shape(Rectangle)
) where
data Shape = Circle | Rectangle deriving (Show)
I then do this:
cd ~/Desktop
ghci
ghci> :m +Shapes
<no location info>:
Could not find module `Shapes'
It is not a module in the current program, or in any known package.
ghci> import Shapes
<no location info>:
Could not find module `Shapes'
It is not a module in the current program, or in any known package.
Why do I get this error?
I also tried compiling first with ghc -c Shapes.hs. It still doesn't work.
I installed the "Haskell Platform 2013.2.0.0 for Mac OS X, 64 bit" from haskell.org on my OS X 10.9.2 Mavericks. I also followed their ghc-clang-wrapper instructions.
Update:
Someone suggested doing :l Shapes.hs first. The problem is that :l Shapes.hs loads the entire Shapes file, meaning I have access to the Circle value constructor even if I did not export it. See my earlier question: Why can I use this "private" value constructor? I want to load only the module. Is this possible?
You need to load your Shapes.hs first by :l Shapes.hs.
Because your Shapes have not been loaded, so :m Shapes will not work.
Because your Shapes does not exist in a compiled package that ghci can find, so import Shapes will not work.
If you only want the exported symbols in scope, after :load a module, you could use :module or import to only import those symbols. For example, after :load Shapes.hs and :module Shapes, Rectangle will in scope but Circle will not.
See:
What's really in scope at the prompt?
:module and :load
A made a module Timeit. I can't import it to GHCi.
Module:
module Timeit (timeit, timeCatch) where
import Data.Time.Clock
timeit::IO ()->IO (Float)
timeit io=do
(time,())<-timeCatch io
return time
timeCatch::IO (a)->IO (Float,a)
timeCatch io=do
start <-getCurrentTime
result <-io
end <-getCurrentTime
return $! (realToFrac (diffUTCTime end start), result)
test=do
putStrLn "What is your name?"
name <- getLine
putStrLn $ "Your name is "++name++"."
GHCi:
theking#ChrisLaptopUbuntu1304:~/Desktop/Haskell$ cd ~/Desktop/Haskell/; ghci
GHCi, version 7.6.3: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> import Timeit
<no location info>:
Could not find module `Timeit'
Perhaps you meant Time (needs flag -package haskell98-2.0.0.2)
I am able to import it into my other programs, just not GHCi.
Note: Am I a haskell noob.
In order for a module to be imported by GHCi, you have to make sure a few things are true.
First, are you in the same directory? By default GHCi will only search the current directory for modules.
Second, have you added the module header? Your code should start with
module Timeit where
...
Third, your file must actually be named Timeit.hs (with that capitalization).
By default Haskell inserts module Main where, which is a problem if your module isn't main.
Last but not least, GHCi seems to require that you use :l Timeit at least once. I'm not sure why this is, but once loaded you can remove it from scope with :m and then import it to your hearts content.
If you've done these things it should import just fine.
To import modules from ghci don't use import, rather say
:m +TimeIt
I loaded two modules (NecessaryModule1.hs and NecessaryModule2.hs as outlinked in Haskell : loading ALL files in current directory path). Now I want to unload NecessaryModule2.hs. I found an 'unload' function in System.Plugins.Load however but it did not work in WinGHCi. The error message I got was :
>unload NecessaryModule2
<interactive>:1:1: Not in scope: `unload'
<interactive>:1:8:
Not in scope: data constructor `NecessaryModule2'
I tried
import System.Plugins.Load
but that did not work. Is there a way to unload modules in the manner described above?
---------------------------------------------------------------------------------------
[RESPONSE TO Riccardo]
Hi Riccardo, I tried your suggestion but I could not get it to work in WinGHCi. I had a file NecessaryModule1.hs as follows :
module NecessaryModule1 where
addNumber1 :: Int -> Int -> Int
addNumber1 a b = a + b
I went to the location of the file via the ':cd' command, and then did :
> :module +NecessaryModule1
<no location info>:
Could not find module `NecessaryModule1':
it is not a module in the current program, or in any known package.
Is this correct? Thanks [EDIT : see below for correction]
---------------------------------------------------------------------------------------
[CORRECTION TO ABOVE]
Just to explain why the above is incorrect (as explained by Riccardo), what needs to be done is the following :
If we have a file NecessaryModule1.hs as follows :
--NecessaryModule1.hs
module NecessaryModule1 where
addNumber1 :: Int -> Int -> Int
addNumber1 a b = a + b
then we do :
> :load NecessaryModule1
[1 of 1] Compiling NecessaryModule1 ( NecessaryModule1.hs, interpreted )
Ok, modules loaded: NecessaryModule1.
> addNumber1 4 5
9
> :module -NecessaryModule1
> addNumber1 4 5
<interactive>:1:1: Not in scope: `addNumber1'
Installed modules
You have to use ghci's commands in order to load (:module +My.Module) and unload (:module -My.Module) installed modules. You can also use :m instead of :module in order to write less, like this:
Prelude> :m +Data.List
Prelude Data.List> sort [3,1,2]
[1,2,3]
Prelude Data.List> :m -Data.List
Prelude> sort [3,1,2]
<interactive>:1:1: Not in scope: `sort'
Remember that the ghci prompt always reminds you the module currently imported: you can have a look at that in order to know what to unload with :m -Module.To.Unload.
Specific files
If the module you're trying to load isn't installed in the system (e.g. you wrote the source and simply saved the file somewhere), you need to use a different command, :load filename.hs. A quicker way is to pass the path to the file directly as a command-line argument to ghci, e.g ghci filename.hs. If you run winghci and you associated it to the .hs extension, simply double-click the file.
In both cases you will get a ghci prompt with the specified module correctly loaded AND imported in scope (provided you don't have get compilation errors instead). As before, you can now use :m [+/-] My.Module to load and unload modules, but please note that this is different from :load because :module assumes you already :loaded what you're trying to get in/out of scope.
E.g., if you have test.hs
module MyModule where
import Data.List
f x = sort x
you may load it by double-clicking it (on windows with winghci), by typing ghci test.hs in a console, or by loading ghci and typing :load test.hs (beware of relative/absolute paths).
Another useful ghci command is :reload, which will recompile the module you loaded before. Use it when you change the source file and you want to quickly update the module loaded in ghci.
Prelude> :load test.hs
[1 of 1] Compiling MyModule ( test.hs, interpreted )
Ok, modules loaded: MyModule.
*MyModule> let xs = [1,2,3] in sort xs == f xs
True
*MyModule> :reload
Ok, modules loaded: MyModule.
:help will give you a complete list of all available commands.