Where does Haskell keep its libraries? [duplicate] - haskell

Is there a way to see Typeclass definition in ghci for a specific type?
For example, Maybe is defined like this:
instance Functor Maybe where
fmap f (Just x) = Just (f x)
fmap f Nothing = Nothing
Can I see this in ghci ?
When, I use :info in ghci, I get this:
Prelude> :i Maybe
data Maybe a = Nothing | Just a -- Defined in `Data.Maybe'
instance Eq a => Eq (Maybe a) -- Defined in `Data.Maybe'
instance Monad Maybe -- Defined in `Data.Maybe'
instance Functor Maybe -- Defined in `Data.Maybe'
instance Ord a => Ord (Maybe a) -- Defined in `Data.Maybe'
instance Read a => Read (Maybe a) -- Defined in `GHC.Read'
instance Show a => Show (Maybe a) -- Defined in `GHC.Show'
In the above output, I want to see how it is defined in Data.Maybe as an instance for Functor. Anyway to see that in ghci ?

No, it's not possible – not just for instances but for anything. GHC only registers the compiled version of a package, so the source code generally won't be available to ghci.
Probably, most often you'll be using stuff from Hackage; in that case it's very simple to find the source code of such instances by hoogling the module, locating the class or data declaration, and clicking on source.
When you don't have internet access or whatever else reason you can't hoogle online, you first need to find out in what package the module is included. The easiest way to do that:
$ ghc-pkg find-module Data.Maybe
/usr/local/haskell/lib/ghc-7.6.2/package.conf.d
   base-4.6.0.1
   haskell2010-1.1.1.0
~/.ghc/x86_64-linux-7.6.2/package.conf.d
Then, as I said, GHC doesn't know where the source code to these packages is located – in fact it might not even be available on your system! But if you've installed the package (or one that depends on it) with cabal install, it will be there, by default in ~/.cabal/packages/hackage.haskell.org/PᴀᴄᴋᴀɢᴇNᴀᴍᴇ (as a compressed archive, but that's not a big hurdle). Within the package project folder, you can simply locate the module via the directory structure, which represents the module hierarchy.
Other packages, like your example of Data.Maybe (package haskell2010), may have come right with your installation of GHC, e.g. the Haskell platform. In that case, I believe the easiest thing is to search there for the Haddock documentation file. In my case,
$ find /usr/local/haskell -name 'Data-Maybe.html' | head -n1 | xargs firefox
That'll open up the equivalent to what hoogle links you to (but on your local HD), where you can also browse the source code in a user-friendly way.

Related

How to introspect an Haskell file to get the types of its definitions

I have many files that must be processed automatically. Each file holds the response of one student to an exercise which asks the student to give definitions for some functions given a type for each function.
My idea is to have an Haskell script that loads each student file, and verifies if each function has the expected type.
A constraint is that the student files are not defined as modules.
How can I do this?
My best alternative so far is to spawn a GHCi process that will read stdin from a "test file" with GHCi commands, for example:
:load student1.hs
:t g
... and so on ...
then parse the returned output from GHCi to find the types of the functions in the student file.
Is there another clean way to load an arbitrary Haskell file and introspect its code?
Thanks
Haskell does not save type information at runtime. In Haskell, types are used for pre-runtime type checking at the static analysis phase and are later erased. You can read more about Haskell's type system here.
Is there a reason you want to know the type of a function at runtime? maybe we can help with the problem itself :)
Edit based on your 2nd edit:
I don't have a good solution for you, but here is one idea that might work:
Run a script that for each student module will:
Take the name of the module and produce a file Test.hs:
module Test where
import [module-name]
test :: a -> b -> [(b,a)]
test = g
run ghc -fno-code Test.hs
check the output does not contain type errors
write results into a log file
I think if you have a dynamically determined number of .hs files, which you need to load, parse and introspect, you could/should use the GHC API instead.
See for example:
Using GHC API to compile Haskell sources to CORE and CORE to binary
https://mail.haskell.org/pipermail/haskell-cafe/2009-April/060705.html
These might not be something you can use directly — and I haven't done anything like this myself so far either — but these should get you started.
See also:
https://wiki.haskell.org/GHC/As_a_library
https://hackage.haskell.org/package/hint
The closest Haskell feature to that is Data.Typeable.typeOf. Here's a GHCi session:
> import Data.Typeable
> typeOf (undefined :: Int -> Char)
Int -> Char
> typeOf (undefined :: Int -> [Char])
Int -> [Char]
> typeOf (undefined :: Int -> Maybe [Char])
Int -> Maybe [Char]
> :t typeOf
typeOf :: Typeable a => a -> TypeRep
Under the hood, the Typeable a constraint forces Haskell to retain some type tags until runtime, so that they can be retrieved by typeOf. Normally, no such tags exist at runtime. The TypeRep type above is the type for such tags.
That being said, having such information is almost never needed in Haskell. If you are using typeOf to implement something, you are likely doing it wrong.
If you are using that to defer type checks to run time, when they could have been performed at compile time, e.g. using a Dynamic-like type for everything, then you are definitely doing it wrong.
If the function is supposed to be exported with a specific name, I think probably the easiest way would be to just write a test script that calls the functions and checks they return the right results. If the test script doesn't compile, the student's submission is incorrect.
The alternative is to use either the GHC API (kinda hard), or play with Template Haskell (simpler, but still not that simple).
Yet another possibility is to load the student's code into GHCi and use the :browse command to dump out everything that's exported. You can then grep for the term you're interested in. That should be quite easy to automate.
There's a catch, however: foo :: x -> x and foo :: a -> a are the same type, even though textually they don't match at all. You might contemplate trying to normalise the variable names, but it's worse: foo :: Int -> Int and foo :: Num x => x -> x don't look remotely the same, yet one type is an instance of the other.
...which I guess means I'm saying that my answer is bad? :-(

How to view Typeclass definitions and a type's Typeclass implementations [duplicate]

Is there a way to see Typeclass definition in ghci for a specific type?
For example, Maybe is defined like this:
instance Functor Maybe where
fmap f (Just x) = Just (f x)
fmap f Nothing = Nothing
Can I see this in ghci ?
When, I use :info in ghci, I get this:
Prelude> :i Maybe
data Maybe a = Nothing | Just a -- Defined in `Data.Maybe'
instance Eq a => Eq (Maybe a) -- Defined in `Data.Maybe'
instance Monad Maybe -- Defined in `Data.Maybe'
instance Functor Maybe -- Defined in `Data.Maybe'
instance Ord a => Ord (Maybe a) -- Defined in `Data.Maybe'
instance Read a => Read (Maybe a) -- Defined in `GHC.Read'
instance Show a => Show (Maybe a) -- Defined in `GHC.Show'
In the above output, I want to see how it is defined in Data.Maybe as an instance for Functor. Anyway to see that in ghci ?
No, it's not possible – not just for instances but for anything. GHC only registers the compiled version of a package, so the source code generally won't be available to ghci.
Probably, most often you'll be using stuff from Hackage; in that case it's very simple to find the source code of such instances by hoogling the module, locating the class or data declaration, and clicking on source.
When you don't have internet access or whatever else reason you can't hoogle online, you first need to find out in what package the module is included. The easiest way to do that:
$ ghc-pkg find-module Data.Maybe
/usr/local/haskell/lib/ghc-7.6.2/package.conf.d
   base-4.6.0.1
   haskell2010-1.1.1.0
~/.ghc/x86_64-linux-7.6.2/package.conf.d
Then, as I said, GHC doesn't know where the source code to these packages is located – in fact it might not even be available on your system! But if you've installed the package (or one that depends on it) with cabal install, it will be there, by default in ~/.cabal/packages/hackage.haskell.org/PᴀᴄᴋᴀɢᴇNᴀᴍᴇ (as a compressed archive, but that's not a big hurdle). Within the package project folder, you can simply locate the module via the directory structure, which represents the module hierarchy.
Other packages, like your example of Data.Maybe (package haskell2010), may have come right with your installation of GHC, e.g. the Haskell platform. In that case, I believe the easiest thing is to search there for the Haddock documentation file. In my case,
$ find /usr/local/haskell -name 'Data-Maybe.html' | head -n1 | xargs firefox
That'll open up the equivalent to what hoogle links you to (but on your local HD), where you can also browse the source code in a user-friendly way.

Generalized type-defaulting rules

Haskell's type-defaulting rules defaults a type variable a with constraints (C1 a,...,Cn a) if:
The type variable a appears in no other constraints
All the classes Ci are standard.
At least one of the classes Ci is numeric
This makes sense to me but it's also very limited: in practice it means that you always have to specify the type when it is ambiguous when you work with custom classes. For example, this doesn't compile:
class (Show a) => MyShow a where
myShow :: a -> String
myShow = show
instance (MyShow a) => MyShow (Maybe a) where
myShow Nothing = "Nothing"
myShow (Just x) = "Just " ++ (myShow x)
main = print $ myShow Nothing -- ambiguous
GHCi extends this set of rules in this way:
All of the classes Ci are single-parameter type classes.
At least one of the classes Ci is numeric, or is Show, Eq, or Ord.
and GHC has an extension called ExtendedDefaultRules that enable these rules. However this extension is very specific: it works only on GHC and with standard classes. For instance, one can think about libraries that don't use the standard library. In that case, the GHCi extension won't work.
My question is: the only way to extend the Haskell's type-defaulting rules like GHCi does is with compiler extensions? And more generic: is there a way to define type-defaulting based on some rules on the constraints in Haskell 98?
There is no way to do what you want.
The current situation is impoverished by design. The idea was to do something minimal that could be extended in the future when we have a good design.

How can I view the definition of a function in Haskell/GHCi?

I'm using Haskell 2010.1.0.0.1 with GHC 6. Typing :t at the GHCi prompt followed by the name of a function shows us the type of the function. Is there a way to view the function definition as well?
Not currently.
The closest command to what you want is :info
:info name ...
Displays information about the given name(s). For example, if name is a class, then the class methods and their types will be printed; if name is a type constructor, then its definition will be printed; if name is a function, then its type will be printed. If name has been loaded from a source file, then GHCi will also display the location of its definition in the source.
For types and classes, GHCi also summarises instances that mention them. To avoid showing irrelevant information, an instance is shown only if (a) its head mentions name, and (b) all the other things mentioned in the instance are in scope (either qualified or otherwise) as a result of a :load or :module commands.
like so:
Prelude> :info ($)
($) :: (a -> b) -> a -> b -- Defined in GHC.Base
infixr 0 $
You can though, see the source for identifiers generated by the haddock tool, on Hackage.
Look up the module on Hackage
Click on the source link
Note that "?src" is a valid command in lambdabot, on the #haskell IRC channel, and does what you'd expect.
> ?src ($)
> f $ x = f x
I don't think so. You can use :i for a little bit more information (more useful for infix operators and data constructions, etc.), but not the definition:
ghci> :i repeat
repeat :: a -> [a] -- Defined in GHC.List
You can use hoogle to quickly find the documentation for a standard library function, which on the right has a link to go to the source. It's still a few clicks away though.
Nope, can't do that. Some fun things you, the Haskell beginner, can do:
On the HTML haddock documents, click on "source"... study the source.
:browse to find all of the definitions exported by a module
Use :help for the obvious result
use the web interface of hoogle to search for functions, or install hoogle locally!
?
Profit!

Is there no standard (Either a) monad instance?

I was under the impression that there was an instance for Either a somewhere, but I can't seem to find it. I have tried importing Control.Monad, Control.Monad.Instances and Data.Either as shown
module Main where
import Control.Monad
import Data.Either
import Control.Monad.Instances
test :: [Either a b] -> Either a [b]
test = sequence
main = return ()
but ghc tells me that it could not deduce (Monad (Either a)). Adding
instance Monad (Either a) where
return = Right
Right b >>= f = f b
Left a >>= _ = Left a
makes the code compile, but this instance declaration seems so general that it doesn't make sense to me if it isn't already out there in some standard module. If it is, where should I look to find it, and if it isn't, is there then a reason for this?
-------------- EDIT ---------------
Be aware that I now think that the answer by user31708 below ("As of base 4.6, the instance is in Data.Either itself.") is currently the correct answer. I am not sure of the proper protocol of reassigning the selected answer in this case, where the selected answer was the correct answer at the time that the question was asked, so I have left it as it is. Please correct me, if there is another guideline for this.
This instance has been added in base 4.3.x.x, which comes with ghc 7. Meanwhile, you can use the Either instance directly, or, if you are using Either to represent something
that may fail you should use ErrorT monad transformer.
As of base 4.6, the instance is in Data.Either itself.
There is not an instance for Either a, but there is for Either String in Control.Monad.Error. (Actually, it's for Error e => Either e, IIRC).
I believe there's something in Control.Monad.Error - don't have anything to check, though.

Resources