I was unable to reduce this to a minimal example, but it's not hard to recreate. I've observed this all the way back to GHC 8.8, and perhaps earlier. Both Mac and Linux. (However, I think this is a regression, i.e., older GHCs--from back about 3 years ago--didn't have this issue. Though I don't have any specific info on versions where it was not an issue.)
The numbers reported below are with GHC 9.8.1.
To replicate, you'll need to have SBV installed. (https://hackage.haskell.org/package/sbv)
For this program:
import Data.SBV
import Data.SBV.Tools.CodeGen
import Documentation.SBV.Examples.Crypto.SHA
main :: IO ()
main = compileToC (Just "testOutput_delete") "sha512" $ do
cgOverwriteFiles True
let algorithm = sha512P
hInBytes <- cgInputArr 64 "hIn"
blockBytes <- cgInputArr 128 "block"
let hIn = chunkBy 8 fromBytes hInBytes
block = chunkBy 8 fromBytes blockBytes
result = hashBlock algorithm hIn (Block block)
cgOutputArr "hash" $ concatMap toBytes result
I'm seeing:
$ time ghc -e main a
ghc -e main a 62.22s user 9.47s system 85% cpu 1:24.18 total
That's kind of slow, but not too bad. But when I compile:
$ ghc a.hs
Loaded package environment from /Users/leventerkok/.ghc/x86_64-darwin-9.8.1/environments/default
[1 of 2] Compiling Main ( a.hs, a.o )
[2 of 2] Linking a
time ./ald: warning: ignoring duplicate libraries: '-lm'
$ time ./a
./a 820.27s user 15.34s system 99% cpu 14:04.02 total
That is significantly slower; in fact 10 times slower than the interpreted code. Compiling with optimizations (-O2) doesn't change the run-time.
I'd appreciate any insights into what might be going wrong.
Thanks Sebastian. I wasn't aware of or-patterns; and that proposal does indeed seem to address this concern greatly! I'd be a customer of this feature if it lands in GHC from day one.
I'll copy the comment I leaved there for support, and a possible simplification that might motivate an implementor:
I'd very much love to see this supported in GHC. It'd make the life of the "working industry programmer" significantly better.
If it helps simplify design/implementation, you can outlaw binding any parameters in the "or" case. I.e., you can pattern-match multiple constructors, so long as no variables are bound in any of those matches. This is a simplification, and I doubt it would take away much from usability in practice, yet deliver a nice solution to practical problems. (Of course, if it doesn't add extra complication, do allow them; but it's an option perhaps for the first version of an implementation?)
Excellent point Simon. You're pointing out the cases where the analysis will be over/under-approximations, almost by necessity. Since the motivation is to "aid" in figuring out what code the user needs to worry-about, I'd suggest you should not warn on the first example you gave, but do warn in the second. Perhaps the rule of thumb is:
But the implementor can choose a different guideline, based on her experience; and this would still aid greatly in either case.
In long running projects, it is common that a new constructor gets added to an existing data-type. The question then becomes what parts of the code we need to modify to support this new constructor. It would be great if there was a way for ghc (or ghci
) to report, for a given constructor, all locations where the program implicitly matches against it, i.e., the constructor gets matched against a wildcard.
This facility would greatly aid in code maintenance and refactoring tasks.
Consider a data-type with lots of constructors:
data X = X1 | X2 | ... | Xn
we might have many places that only care for a few of these:
f X1 = rhs1
f X2 = rhs2
f _ = error "can't happen"
or
case expr of
X1 -> rhs1
X5 -> rhs2
_ -> error "can't happen"
If we now add a new constructor XK
that didn't exist before, we'd like GHC to tell us where in our code this constructor is implicitly matched; so we can review and decide if the "ignoring" behavior is OK, or we should add relevant code.
Obviously, this should work just the same if the constructor has arguments, matched in a nested way, etc. I imagine it might be a ghci command:
:implicit_match XK
or perhaps a ghc command-line option which spits out a report. The details aren't particularly important and if implemented, the implementors can choose the most appropriate design.
When these sorts of requests come, it is common for people to point out that this may not be possible in general. And indeed, I do not expect GHC to give a precise answer: It might report false positives (i.e., where the constructor wouldn't be matched, but it'd still be reported as such due to data-path considerations), or false negatives (i.e., the constructor would be matched, but the analysis gets fooled for some reason.)
And that's perfectly fine! Nobody is expecting for this analysis to be 100% accurate. Just like the current pattern-match warnings, the output of this command (in ghci), or analysis printed by ghc might be an over/under-approximation.
Just because the problem is unsolvable in general, doesn't mean the information GHC will provide will be useless; quite to the contrary, it'd go along way for code maintenance in both industrial and academic contexts. If necessary, the output of the command can have a disclaimer to the same effect.
Easier use of :def
commands
ghci's :def
command is useful in defining nice macros.
As far as I can tell, these when these macros are later used, tab-completion does nothing when passing arguments to the command defined. It would be nice if there was a mechanism to allow the user to specify what kind of completion would be appropriate for it. I can think of 3 obvious choices:
Other options might be possible, but this looks like a good start.
This is root caused now to including a file that depends on the plug-in being developed. For details, see: https://github.com/haskell/haddock/issues/1369#issuecomment-1114151260
I’m not sure if the fix should be on ghc/ghci/cabal or haddock. But there’s a workaround as described in the above link for end-users.
This was filed as a haddock problem as well: https://github.com/haskell/haddock/issues/1369
Unfortunately, it's not getting any attention there, and I still feel this is more like a ghc issue in the end; as haddock isn't really about "loading" but generating docs.
Re-opening with the hope that it'll receive some new attention.
Project successfully compiled with GHC 9.0.1; but building haddock fails with an apparent GHCi failure message
Since the failure is during haddock, the easiest is to replicate would be to clone the project and try it yourself.
git clone https://github.com/LeventErkok/sbvPlugin.git
cd sbvPlugin
cabal new-haddock --haddock-option=--hyperlinked-source --haddock-option=--no-warnings
Pretty quickly, you get:
Resolving dependencies...
Build profile: -w ghc-9.0.1 -O1
In order, the following will be built (use -v for more details):
- sbvPlugin-9.0.1 (lib) (first run)
Configuring library for sbvPlugin-9.0.1..
Preprocessing library for sbvPlugin-9.0.1..
Running Haddock on library for sbvPlugin-9.0.1..
Warning: The documentation for the following packages are not installed. No
links will be generated to these packages: QuickCheck-2.14.2,
hashable-1.3.1.0, libBF-0.6.2, uniplate-1.6.13, unordered-containers-0.2.13.0,
random-1.2.0, sbv-8.13, splitmix-0.1.0.3, syb-0.7.2.1, async-2.2.3
Haddock coverage:
100% ( 6 / 6) in 'Data.SBV.Plugin.Data'
100% ( 11 / 11) in 'Data.SBV.Plugin'
haddock: ^^ Could not load '_sbvPluginzm9zi0zi1zminplace_DataziSBVziPluginziPlugin_plugin_closure', dependency unresolved. See top entry above.
GHC.Runtime.Linker.getHValue
During interactive linking, GHCi couldn't find the following symbol:
sbvPluginzm9zi0zi1zminplace_DataziSBVziPluginziPlugin_plugin_closure
This may be due to you not asking GHCi to load extra object files,
archives or DLLs needed by your current session. Restart GHCi, specifying
the missing library using the -L/path/to/object/dir and -lmissinglibname
flags, or simply by naming the relevant files on the GHCi command line.
Alternatively, this link failure might indicate a bug in GHCi.
If you suspect the latter, please report this as a GHC bug:
https://www.haskell.org/ghc/reportabug
cabal: Failed to build documentation for sbvPlugin-9.0.1.
Haddock documentation is produced
Optional:
@mpickering From @wz1000's comment, I understand the intention was that it'd default to ~/.ghc
. If you don't set $XDG_DATA_HOME
, it doesn't do that, so in that sense yes; this is broken; though with an easy workaround.
I think you mean XDG_DATA_HOME
?
I can confirm that if I set that env variable everything works OK; so there's at least a workaround.
Installed ghc 9.2.1 via ghcup; everything seems to be functioning OK.
Except, ghci-9.2.1 does not seem to be using ~/.ghc/ghci_history
file; i.e., the history is neither saved nor is loaded upon start.
Note that editing facilities seem to be working just fine; i.e., Ctrl-R, up-arrow, history recall all works so long as you're within the session. It just seems that the history is just not persisted or reloaded.
I'm on MacOS X; if that makes any difference.
Is this a change in 9.2.1? Maybe I'm missing a new configuration option?