I am getting acquainted to Haskell, currently writing my third "homework" to some course I found on the web. The homework assignment needs to be presented* in a file, named Golf.hs, starting with module Golf where. All well and good, this seems to be idiomatic in the language.
However, I am used to python modules ending in if __name__ == "__main__:, where one can put tests over the module, including during module development.ghc doesn't seem happy with such an approach:
$ ghc Golf.hs -o Golf && ./Golf
<no location info>: error:
output was redirected with -o, but no output will be generated
Even though using cabal seems to be the norm, I would like to also understand the raw command-line invocations, that make programs work. ghci seems to be another approach to testing newly written code, yet reloading modules is peta. What is the easiest way to write some invocations of my functions with predefined test data and observe on stdout the result?
* - for students, who actually attend the course, I just follow the lecture notes and strive to complete the homeworks
Golf2.hs:
{-# OPTIONS_GHC -Wall #-}
module Golf2 where
foo :: Int -> Int
foo n = 42
main = putStr "Hello"
The output:
$ ghc Golf2.hs -o Golf2
[1 of 1] Compiling Golf ( Golf2.hs, Golf2.o )
Golf2.hs:6:5: warning: [-Wunused-matches] Defined but not used: ‘n’
Golf2.hs:8:1: warning: [-Wmissing-signatures]
Top-level binding with no type signature: main :: IO ()
<no location info>: error:
output was redirected with -o, but no output will be generated
because there is no Main module.
ghci is a really useful tool for learning!
When you only have one module, it's very easy, too. Start ghci, then :l Golf.hs. This will load your file. Then you'll be able to type foo 342 and see "42" displayed, or main and see "hello". You can edit the file, then use :reload or :r to load your changes. Real World Haskell has a good intro to using ghci.
This is a little easier than using ghc or tools like cabal, and all you really need while you're learning the very basics.
If you want to use ghc-the-compiler (instead of its interactive variant ghci), you might use the -main-is option.
From the docs:
-main-is⟨thing⟩
The normal rule in Haskell is that your program must supply a main function in module Main. When testing, it is often convenient to
change which function is the “main” one, and the -main-is flag allows
you to do so. The ⟨thing⟩ can be one of:
A lower-case identifier foo. GHC assumes that the main function is Main.foo.
A module name A. GHC assumes that the main function is A.main.
A qualified name A.foo. GHC assumes that the main function is A.foo.
So, try ghc -main-is Golf2 Golf2.hs -o Golf2 && ./Golf2.
Related
I’m writing a type checker plugin that can be loaded unconditionally, but it should do things only whenever used in the context of a module that already has some definitions loaded. I’ve hacked together the following function to try resolving a qualified name, but it's using internal details of GHC that I feel I should not be using:
lookupOrigMaybe :: Module -> OccName -> TcPluginM (Maybe Name)
lookupOrigMaybe mod occ = do
hsc_env <- getTopEnv
unsafeTcPluginTcM $ liftIO $ updateNameCache (hsc_NC hsc_env) mod occ $ \cache0 -> do
let name = lookupOrigNameCache cache0 mod occ
return (cache0, name)
I would like to do this in a nicer way instead. It should be enough to check that the given module is already loaded, since for my use case, if the module is there but the name isn’t, then all bets are off and my plugin might as well just error out. So I was hoping I could use findImportedModule followed by lookupOrig, but alas, findImportedModule fails me in one of two ways:
If I don’t specify the package (i.e. use NoPkgQual), findImportedModule seems to return a Found{} result even when the module isn’t actually loaded yet, leading to lookupOrig failing:
attempting to use module ‘main:Cortex.Stem.Relation.Types’ (Cortex.Stem.Relation.Types) which is not loaded
If I do specify the package (using ThisPkg), then findImportedModule chokes in situations when the given unit would come “later” in the dependency graph than the currenty processed one:
panic! (the 'impossible' happened)
GHC version 9.5.20220830:
findImportModule
Cortex.Stem.Relation.Types
"main"
Just ghc-bignum
main
[ghc-bignum, cortex-prim]
Call stack:
CallStack (from HasCallStack):
callStackDoc, called at compiler/GHC/Utils/Panic.hs:188:37 in ghc-lib-0.20220830-FvKByKwp6ri5ICk6wiQO8W:GHC.Utils.Panic
pprPanic, called at compiler/GHC/Unit/Finder.hs:160:32 in ghc-lib-0.20220830-FvKByKwp6ri5ICk6wiQO8W:GHC.Unit.Finder
Please report this as a GHC bug: https://www.haskell.org/ghc/reportabug
So my question then, is what is the recommended way of looking up a loaded definition opportunistically from a type checker plugin?
I just had the following error with a Haskell project.
I made a cabal file for a Haskell project to install it properly. This project compiled well when I build my binary with ghc --make but when I build my cabal file with cabal build , I had the following error:
src/Text/MarkIt/Verif.hs:12:3: error:
parse error (possibly incorrect indentation or mismatched brackets)
The beginning of my file is :
module Text.MarkIt.Verif where
import qualified Control.Monad.Trans.State.Strict as Tr
import Text.MarkIt.Types
import Data.List
class Verif a where
summary :: a -> Tr.State StatDoc ()
instance Verif MarkIt where
summary (MarkIt meta blocks) = do
summary meta
mapM_ summary blocks -- This is the boring line
instance Verif Meta where
summary meta = mapM_ summary (mAuthors meta)
I tried to rebuild my executable with ghc and it compile well. I checked if their were no hidden char, tabulation, incorrect end of line, ... nothing!
I finally removed the following line from my cabal file :
default-language: Haskell2010
Then, my cabal file was build and installed fine !
Does someone could explain me why this cabal option cause a such problem at this precise point of my file?
What is different with the Haskell 2010 language specification to cause this problem ?
By default, GHC is in Haskell 98 mode, which enables the following relaxation from the standard:
In Haskell 98 mode and by default (but not in Haskell 2010 mode), GHC is a little less strict about the layout rule when used in do expressions. Specifically, the restriction that “a nested context must be indented further to the right than the enclosing context” is relaxed to allow the nested context to be at the same level as the enclosing context, if the enclosing context is a do expression.
https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/bugs.html#context-free-syntax
A comment in the GHC source explains further:
strictly speaking non-standard, but we always had this on implicitly before the option was added in 7.1, and turning it off breaks code, so we're keeping it on for backwards compatibility.
https://gitlab.haskell.org/ghc/ghc/blob/d0b45ac6984f245bce9de7ffcc7dad4a0046d344/compiler/main/DynFlags.hs#L2310
When you enable the Haskell2010 mode in your cabal file, that bug gets fixed, and the syntax of your file is rejected. so do blocks must be indented further than the enclosing context,
summary (MarkIt meta blocks) = do
summary meta
mapM_ summary blocks
-- ^ indented
I have decided to use my own Prelude for a larger project (containing some libraries and some executables). The Prelude doesn't export some partial functions and exports some common functions (i.e. from Control.Monad etc.). However, I am fighting with the way how to do it. I have tried:
use base-noprelude. Create Prelude.hs in module my-common-module.
Same as above, but in the my-common-module create My.Prelude instead. In every other module create a directory 'prelude', put it into hs-source-dirs cabal section, create a file prelude/Prelude.hs with import My.Prelude
The problem is that in 1) I cannot just run ghci, as I get conflicting base and my-common-module. In 2) ghci works, cabal repl somehow doesn't as it fails mysteriously with 'attempting to use module ‘Prelude’ (prelude/Prelude.hs) which is not loaded'. Additionally, base-noprelude doesn't seem to like ghcjs, which I want to use for part of the project (code sharing).
It seems to me the only way currently is to start each and every file with:
import Prelude ()
import My.Prelude
or
{-# LANGUAGE NoImplicitPrelude #-} -- or extensions: NoImplicitPrelude in .cabal
...
import My.Prelude
The 'extensions: NoImplicitPrelude' option seems to me best as it requires every file to import My.Prelude otherwise it won't work. Am I missing some obvious way that would achieve custom Prelude and at the same time work with cabal repl and ghcjs?
Update: base-noprelude works with GHCJS when I manually remove the reexport of GHC.Event.
Update: Ok, I spent some time with this and I should have spent more. It seems to me that 1) is the right way to go. cabal repl works (thanks Yuras), ghci must be loaded with ghci -hide-package base and works too.
I ended up with this setup that seems to work:
Create a special package my-prelude. This package exports the Prelude, can contain other modules, it can depend on base. You may need to use {-# LANGUAGE NoImplicitPrelude #-} in some modules to avoid circular dependencies. E.g. you may want to have some orphan instances defined and exported by your custom Prelude in separate files (e.g. Orphans.Lib_aeson), these files need the NoImplicitPrelude.
In your main project, libraries etc. change the dependencies in cabal from base to base-noprelude, my-prelude.
What works:
cabal repl
ghci/runghc works, but you have to start it with ghci -hide-package base; otherwise there will be conflict between base and my-prelude
What does not work:
cabal repl in the my-prelude package.
I am under the impression that until recently cabal repl automatically imported all the imports from the currently loaded file. That is if I had a file src/Main.hs:
module Main where
import qualified Data.Vector as V
main = putStrLn "foo"
And I would load it in cabal repl with :l src/Main.hs, V would be available without any further work.
I believe this behavior changed during the change to ghc/ghci 7.10, but I am not sure. Is there any option that would let me change that back to the way it was before?
edit: As it happens I have actually compiled the modules, which was part of the problem. See Ørjan Johansens comment below.
From the GHC User's Guide:
The syntax in the prompt *module indicates that it is the full top-level scope of module that is contributing to the scope for expressions typed at the prompt. Without the *, just the exports of the module are visible.
NOTE: for technical reasons, GHCi can only support the *-form for modules that are interpreted. Compiled modules and package modules can only contribute their exports to the current scope. To ensure that GHCi loads the interpreted version of a module, add the * when loading the module, e.g. :load *M.
In other words, add a * before the module name when loading.
It appears to be impossible to introspect type class constraints on functions and data types and such. However, ghci appears to do it.
Prelude> :t show
show :: (Show a) => a -> String
So... somehow it knows the type class constraint since it's printing it out. How is it doing that?
The information is kept in interface files (module.hi). To get at it from in a running program you would need to find and read the .hi files (the Hint package on Hackage does this, I believe); since ghci reads the .hi files in the course of compiling to bytecode, it has that information conveniently available.
You can see what's in a .hi file with ghc --show-iface module.hi.
The separately compiled "binaries" are the ".hi" files. These contain all the type information so that you can write code that uses them, and they contain all the type class definitions and all the type class instances so that your code can use or extend them.
Thus ghci compile source to ".hi" and loads all the dependent ".hi" files. This gives it perfect knowledge of all the types. What ghci does not need to do is go back to the source of all the imported modules, it only needs the ".hi" files.