When I compile a Haskell file with ghci, typically with :load, and if there is no type error, all the expressions are loaded in the ghc interpreter. It's very nice: I can play around with :t to figure out the type of various expressions.
My problem is: if there is a tiny error somewhere, ghci is not able to load anything (not even the imported modules!!), which makes finding the right types even more difficult. I always do the same: comment out all the bits that do not typecheck, find the relevant types wiht :t in ghci, and de-comment.
But this is so tedious! Is there a better workflow for "partially compiling" a Haskell source code?
As #MikhailGlushenkov pointed out in the comments, the solution is to use the -fdefer-type-errors flag to GHCi.
Related
Is there a way to get GHCi to produce better exception messages when it finds at runtime that a call has produced value that does not match the function's pattern matching?
It currently gives the line numbers of the function which produced the non-exhaustive pattern match which though helpful at times does require a round of debugging which at times I feel is doing the same set of things over and over. So before I tried to put together a solution I wanted to see if something else exists.
An exception message that in addition to giving the line numbers shows what kind of call it attempted to make?
Is this even possible?
Try turning on warnings in ghci. This enables the compile time warnings you can get with ghc by passing -W, for example. You can do this several ways:
ghci -fwarn-incomplete-patterns
Or Neil Mitchell describes how he sets this up in his .ghci. Here is the relevant excerpt:
:set -fwarn-incomplete-patterns
You can manually enter this at ghci as well, but it would be a pain to do so each time you start it. Entered this way, it only works for statements entered at the prompt, not for loading files with :l. Instead you can put this comment at the top of the file you want to warn about incomplete patterns:
{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
I recognize that this is something of a non-answer to your question, but my impression is that among veteran Haskell programmers there's a general consensus that non-exhaustive patterns should be avoided in the first place, even to the point of using -Werror to generate errors instead of just warnings.
I'm not sure how well that works in combination with GHCi, however, especially if you're writing functions at the prompt instead of loading a file--I can imagine it getting in the way more than it helps for working interactively. Running GHCi with the appropriate command-line flags seems to get the desired result for me, though.
If you want a more drastic solution to non-exhaustive patterns, you could always port Catch to work with modern GHC versions. Heh.
Beyond that, if you're using non-exhaustive patterns because the function really, truly, should never be called with some values, the missing cases can be filled in with something like error $ "function foo called with ridiculous arguments " ++ show blahBlah, if knowing the invalid arguments would be helpful. Alternately, you could try to rework your code or define more specialized data types such that functions can always do something sensible with any non-bottom argument.
Otherwise, I think you're stuck with awkward debugging.
I am a data scientist familiar with languages such as R and python.
I have been trying to learn haskell for two months.
There is a module people employ to deal with frames in haskell similarly to common packages in those other languages (tidyverse in R and pandas in python).
The problem is: the common function for extracting data type for a csv is simply returning a message error:
tableTypes "base" "base.csv"
<interactive>:2:1: error:
• No instance for (Show Language.Haskell.TH.Lib.DecsQ)
arising from a use of ‘print’
• In a stmt of an interactive GHCi command: print it
I cannot understand what this message means and I could not find any answer on Google. Could someone help me solve it?
Link to the module: http://hackage.haskell.org/package/Frames
You've stumbled into a case that's involves some advanced features of Haskell. The problem is that tableTypes "base" "base.csv" is a template haskell splice. For some reason, a few years back ghc was modified to allow bare expressions at the top level as splices, instead of requiring the standard splice syntax of $(expression generating code to splice).
But the bare expression syntax is incompatible with ghci. If you enter a bare expression in ghci, it tries to evaluate and print it (with some special rules for expressions that result in IO values).
When ghci evaluates tableTypes "base" "base.csv" it gets a result back that's not an instance of Show, because the template haskell Q environment is not printable. It contains a bunch of functions.
You have a few options here, depending on what you actually are trying to do. You could use runQ in ghci to dump the AST generated by the splice. That's probably not what you want. That's more likely to be a tool that's useful when you're developing a splice than for testing a library that uses them.
You could enable the TemplateHaskell extension within ghci and actually have it perform the splice interactively, but that's somewhat fiddly to get to work and you don't end up seeing much anyway.
I think the most practical solution is to move your code into a file. You can load said file from ghci if you desire - the important part is that in the context of a file, there's no longer any syntactic ambiguity - that's definitely a splice to evaluate while compiling, not an expression to evaluate interactively.
So my questions are:
1) (This is more specific and related to the problem I had) How can I know the default types for numbers, i.e., the Ts in default (T1, ...) being used at the moment in GHCi?
2) Is there a way to make typed code and loaded code behave the same always in GHCi? (excluding the differences related to the fact that typed code is run inside the IO Monad) For example, I should not have to include some kind of extension (e.g., ExtendedDefaultRules) so that the code in a file runs exactly as run in the prompt.
3) How can I invoke GHC and GHCi so that the same code shows the same behavior whether run via GHC or GHCi? (imagine I load the main file of an app and type run main in GHCi)
Thanks
Regarding point 3:
You can make code run exactly in the same way in both ghc and ghci:
use only pure and safe functions. By doing this you know that optimizations or side-effects will not show any different behaviour due to the implementation (as in the question you linked).
No special flag is required. If you do not follow this advice then there is no flag that allows to obtain what you want.
Regarding point 2:
You can make ghci recompile every file and use the interpreter version instead of loading the binary compiled by ghc so you can be sure the code will act as if typed by ghci instead of compiled by ghc. Use the :reload command to force recompilation.
Regarding the types and defaulting (point 1):
GHCi by default uses the extended defaulting rules, which are described here.
Standard defaulting rules basically default only "numbers" (i.e. Num, Fractional etc.). Extended rules are able to default types for things like Eq, Ord and Show.
Note that the default declaration implicit when using ExtendedDefaultRules is:
default ((), Integer, Double)
So, basically, any "free" Eq or Ord constraint is simply defaulted to ().
So you can simply specify ExtendedDefaultRules or NoExtendedDefaultRules to specify exactly which kind of defaulting you want.
This can be done putting the pragmas in the source files {-# LANGUAGE <extension-name> #-} or by specifying -X<extension-name> when compiling with ghc or by using the GHCi directive :set -X<extension-name>.
As noted by dfeur there is a fundamental difference between ghci and ghc: ghci must be able to completely infer the type of the input text when it is inserted. So, obviously, you have to arrange the declarations so that a function doesn't reference an undefined name.
Moreover type defaulting will be applied to each statement which means that, together with the monomorphism restriction (see: What is the monomorphism restriction? and https://wiki.haskell.org/Monomorphism_restriction) ghci may infer more monomorphic types than the ones inferred by ghc when compiling the same code.
You probably want to use NoMonomorphismRestriction when using GHCi (though recent versions of ghci have it disabled by default) and probably in your files too.
Can GHC or some lint tool tell me when I've provided a type signature for a function that could be more polymorphic?
GHC doesn't do this, and a quick search of Hackage turns up nothing.
A simple, but possibly quite effective way to implement such a thing would be to load the module in GHCi, use :browse to get all the type signatures, then load a copy without any type signatures, use :browse again, and compare the two outputs; then just print all the lines that differ beyond parentheses, whitespace and alpha-renaming. However, this wouldn't work perfectly, especially if you have definitions whose types can't be inferred.
I have a feeling such a tool would turn up a lot of false positives in practice.
The :browse, :info and :type GHCi commands are very convenient.
Is it possible to get the same information programmaticaly in a Haskell program? That is, to get the exported functions from a module, the types of stuff, etc.
:browse - when a Haskell program is compiled, no (useful) information is kept about which module something came from, so your program wouldn't be able to access that information.
:type - Unless you're using Data.Typeable, types aren't visible at all at runtime. Types in Haskell are mostly for the compiler to check to correctness/safety of code.
:info - See above.
for getting functions of a module at compile time - the language-haskell-extract package could be interesting to you. It helps you extracting functions according to a regular expression.
http://hackage.haskell.org/package/language-haskell-extract-0.2.1
Daniel Fischer commented:
You can use the GHC API. I'm not aware of a simpler way.
Seems to be fiddly but to work fine. And I guess this is how :info works in GHCi. Thanks for the suggestion.