Finding unused Haskell functions in a module or file? - haskell

Is there a way to automatically find unused functions (and constants) in a module or .hs file? Specifically, I mean those functions that are not used (directly or indirectly) by the functions in the export list of the current module/file.
I know that e.g. Emacs haskell mode has the ability to warn about unused importS as follows:
The import of XXX is redundant
Is there similar tool or method for finding unused functions?
Note: I know this can be done manually by deleting some code and see whether it still compiles. But it's tedious process.

Here are some relevant ghc -W flags:
-Wunused-binds
-Wunused-do-bind
-Wunused-foralls
-Wunused-imports
-Wunused-local-binds
-Wunused-matches
-Wunused-pattern-binds
-Wunused-top-binds
-Wunused-type-patterns
Or just use -Wall. You can get a complete list of ghc flags with ghc --show-options.

Related

Will everything imported by a wildcard use directive ("use some_crate::*") be included in the binary?

If I import everything using * in Rust's use, does the built file include only what I use in the import?
e.g. use std::io::prelude::*
Through LLVM, Rust benefits from aggressive dead code elimination.
In fact, you can see that work by default: unless no_std, code implicitly has the standard prelude in-scope.
For instance, compare trivial printing code versus trivial printing code with a (useless) Box invocation: https://godbolt.org/z/3KWbGeqsh
Only the latter has the relevant Box code generated and compiled in.

find_dependency(Threads) or include(FindThreads) in a package config file

In CMake, we can use find_dependency() in an package -config.cmake file to "forwards the correct parameters for QUIET and REQUIRED which were passed to the original find_package() call." So, naturally we'll want to do that instead of calling find_package() in such files.
Also, for dependency on a threads library, CMake offers us the FindThreads module, so that we write include(FindThreads), prepended by some preference commands, and get a bunch of interesting variables set. So, that's preferable to find_package(Threads).
And thus we have a dilemma: What to put in -config.cmake files, for a threads library dependency? The former, or the latter?
Following a discussion in comments with #Tsyarev, it seems that:
find_package(Threads) includes the FindThreads module internally.
... which means it "respects" the preference variables affecting FindThreads behavioe.
so it makes sense, functionally and aesthetically, to just use find_package() in your main CMakeLists.txt and find_dependency() in -config.cmake.

Module loading options in GHCi

Why does GHCi have so many different commands for loading modules into a session?
Here are ones I'm aware of, together with their rather confusing explanations from :help in ghci:
add [*]<mod> -- add module(s) to the current target set
:module [+/-] [*]<mod> -- set the context for expression evaluation
:load [*]<mod> -- load module(s) and their dependents
:reload <mod> -- reload the current module set. (Note: :help doesn't say that this can take a module argument, but it seems that it can.)
import Mod
What do they each do? How does the asterisk change it? Why are there so many? :(
There are essentially two different concepts at work here: target set and evaluation context.
You work with the target set with :add, :load and :reload, and you work with the evaluation context with :module and import.
The target set is the list of locally available modules that ghci is reading and compiling. Generally you would use this to specify the source that you're working on. ghci will load and compile each of these modules and any dependencies it needs.
You use :load to reset the target set to precisely the given set of modules, and :add to add the given modules to the existing target set.
If you specify modules in the target set with * then they will always be "bytecode-interpreted" - which means they load quickly but don't run as fast as compiled code - otherwise ghci will use a compiled object file if available and bytecode interpret if not.
:reload on its own reloads the entire target set and dependencies. I'm not quite sure exactly what :reload <mod> does but I think it reloads <mod> and dependencies and leaves the rest untouched.
The evaluation context controls what names are in scope at the prompt, and is fully documented here. Modules for adding to the evaluation context can either be local ones in the target set+dependencies, or be "package" ones that have been previously registered with ghc using the ghc-pkg tool (or cabal which calls that eventually). import Foo is just another way of writing :module +Foo.
NOTE: this answer is a mixture of my intuitive understanding from my experience of using ghci and just reading the documentation and trying to integrate the two in my mind. So I may well not have got this 100% accurate!

erlang -import not working

I have an erlang program, compiled with rebar, after the new debian release, it won't compile anymore, complaining about this:
-import(erl_scan).
-import(erl_parse).
-import(io_lib).
saying:
bad import declaration
I don't know erlang, I am just trying to compile this thing.
Apparently something bad happened to -import recently http://erlang.org/pipermail/erlang-questions/2013-March/072932.html
Is there an easy way to fix this?
Well, -import(). is working but it does NOT do what you are expecting it to do. It does NOT "import" the module into your module, nor does it go out, find the module and get all the exported functions and allow you to use them without the module name. You use -import like this:
-import(lists, [map/2,foldl/3,foldr/3]).
Then you can call the explicitly imported functions without module name and the compiler syntactically transforms the call by adding the module name. So the compiler will transform:
map(MyFun, List) ===> lists:map(MyFun, List)
Note that this is ALL it does. There are no checks for whether the module exists or if the function is exported, it is a pure naive syntactic transformation. All it gives you is slightly shorter code. For this reason it is seldom used most people advise not to use it.
Note also that the unit of code for all operations is the module so the compiler does not do any inter-module checking or optimisation at all. Everything between modules like checking a modules existence or which functions it exports is done at run-time when you call a function in the other module.
No, there is no easy way to fix this. The source code has to be updated, and every reference to imported functions prefixed with the module in question. For example, every call to format should be replaced with io_lib:format, though you'd have to know which function was imported from which module.
You could start by removing the -import directives. The compilation should then fail, complaining about undefined functions. That is where you need to provide the correct module name. Look at the documentation pages for io_lib, erl_scan and erl_parse to see which functions are in which module.
Your problem is that you were using the experimental -import(Mod) directive which is part of parameterized modules. These are gone in R16B and onwards.
I often advise against using import. It hurts quick searches and unique naming of foreign calls. Get an editor which can quickly expand names.
Start by looking at what is stored in the location $ERL_LIBS, typically this points to /usr/lib/erlang/lib.

With ghc is there a way to import symbols that are not explicitly exported?

I'm going to guess the answer is 'no', but is there a way to import a symbol from a module that is not explicitly export from said module?
I tried looking up various ghc (6.12.1) flags like -XPackageImports, but I don't see anything that will do what I want? (which is purely for doing some quick & dirty testing without re-compiling some other modules; i don't actually want to write code this way)
No. There isn't even a dirty hack. The .hi files which are used by the type checker to find out the types of things of imported modules only contain info about exported names. The only way to change that is to edit the source file.
No

Resources