If your program has no foreign calls in it, and no
calls to known-unsafe functions (such as
unsafePerformIO) then a crash is always a
BUG in the GHC system, except in one case: If your program
is made of several modules, each module must have been
compiled after any modules on which it depends (unless you
use .hi-boot files, in which case these
must be correct with respect to the
module source).

For example, if an interface is lying about the type
of an imported value then GHC may well generate duff code
for the importing module. This applies to pragmas
inside interfaces too! If the pragma is lying
(e.g., about the “arity” of a value), then duff
code may result. Furthermore, arities may change even if
types do not.

In short, if you compile a module and its interface
changes, then all the modules that import that interface
must be re-compiled.

A useful option to alert you when interfaces change is
-hi-diffs. It will run
diff on the changed interface file,
before and after, when applicable.

If you are using make, GHC can
automatically generate the dependencies required in order to
make sure that every module is
up-to-date with respect to its imported interfaces. Please
see Section 5.6.11, “Dependency generation”.

If you are down to your
last-compile-before-a-bug-report, we would recommend that
you add a -dcore-lint option (for extra
checking) to your compilation options.

So, before you report a bug because of a core dump,
you should probably:

Int, Float, and
Double arithmetic is
unchecked. Overflows, underflows and
loss of precision are either silent or reported as an
exception by the operating system (depending on the
platform). Divide-by-zero may cause an
untrapped exception (please report it if it does).