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.
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?
It turns out that Haddock does not render per-argument docs for type class
methods:
class Foo a where
foo
:: Int -- ^ This string will be ignored by Haddock
-> a
This causes certain issues for users of a library I maintain, because
the methods in my case have quite lengthy signatures. I have always had the descriptions in
the source formatted like that (certainly works for ordinary functions), but
it turns out Haddock does not display them (and does not complain about them
either).
Is there a way to display the per-argument docs with Haddock? Some workaround perhaps?
OK, this was a regression. This thing should work (and worked in version 2.16.1), but stopped (2.17.1 and later).
I have reported this: https://github.com/haskell/haddock/issues/647, should be fixed in version 2.18 (you can see there is a PR for this already).
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.
This feels like a trivial question, but it has been nagging me for a while now: in the course of following 'Real World Haskell', I have been trying out sample code with the Word8 data type, using the Data.ByteString.Lazy.Char8 module. Most of it works fine, but I had to remove type declaration involving the symbol Word8 as ghci would not recognize it. When using the :type ghci on some function involving this type, it is referred to as GHC.Word.Word8, yet replacing Word8 by GHC.Word.Word8 in the code doesn't improve things, and any import statement I have guessed around GHC.Word.Word8 has failed. I have looked online on the hackage site which suggest Data.Word8 but this failed to. Searching for earlier posts on this forum did not give me an answer. I am using:GHCi, version 7.6.3: http://www.haskell.org/ghc/ on Debian 8.
The definition can be found in Data.Word.
For future reference, Hoogle is really nice to look up where symbols come from.
In module B I have documentation with a link 'A.foo', linking to the foo member of module A. In module A I import module B. Haddock renders this as a link to A.html#t:foo, namely pointing at the type foo (which does not exist) not the function foo, which is at A.html#v:foo.
Why does Haddock link to t: for variables that start with a lower case letter? Is that a bug? For 'A.Foo' I can see that it could be a type or a constructor, so there are namespacing issues. For foo it seems a variable is at least most plausible.
Is there any way to fake a link? I am writing this in code samples, so I need it to be rendered as foo. I tried anchors, but they render as the module name, and for direct hyperlinks you have no control over the displayed text.
I considered a post processor (replacing t:[a-z] with v:), but that requires a custom Setup.hs which causes problems and is quite ugly.
I couldn't find any Haddock command line flags to obtain a more reasonable behavior, such as specifying that foo is a variable.
I can't add an import of A to B without introducing circular imports, which is vile to add purely for documentation.
I am running into this problem in the Shake documentation, where as an example removeFilesAfter does not get the right link.
I can partially answer the the first question (Why?); not sure if it is a bug or desired behaviour.
When haddock resolves references in LexParseRn.rename, it tries to look up the identifier in the environment (via lookupGRE_RdrName). This ought to fail. Next it looks as what the thing could mean (using dataTcOccs from GHC’s RnEnv). The relevant lines are:
dataTcOccs :: RdrName -> [RdrName]
-- Return both the given name and the same name promoted to the TcClsName
-- namespace. This is useful when we aren't sure which we are looking at.
dataTcOccs rdr_name
[...]
| isDataOcc occ || isVarOcc occ
= [rdr_name, rdr_name_tc]
[...]
where
occ = rdrNameOcc rdr_name
rdr_name_tc = setRdrNameSpace rdr_name tcName
so it returns the name first interpreted as whatever it was before (likely a link to a value), and then interpreted as a type constructor. How can a regular name be a type constructor? My guess is that this was added when TypeOperators were reformed in GHC 7.6, which now do share the namespace with value-level operators.
Then haddock matches on the result: If the first one is a type constructor, use that, otherwise use the second. So either it was a type constructor before, then this is used. Or it was not, but then the modified version generated by dataTcOccs is to be used.
It seems to me that haddock should just always use the first option here, and the code is just a mislead copy from how multiple results are used when they can actually be resolved.
This was a Haddock bug #228 and Neil's Haddock bug #253 and the fix has been upstream for few months. You can build GHC HEAD and rebuild your documentation or wait for 7.8 and do it then.