F# interactive commands corresponds to ghci :t :i - haskell

I'm learning F# via F# interactive.
Is there commands that acts like GHCi :t, :i?
:t value shows the type of value.
:i type shows the top-level declarations of type.
Reference: fsharp-interactive

In F# Interactive you can just write the name of function to see its type. If, for example, you want to see the types of id, string, or List.map, just write them:
> id;;
val it : ('a -> 'a)
> string;;
val it : (obj -> string) = <fun:it#6-3>
> List.map;;
val it : (('a -> 'b) -> 'a list -> 'b list)
That gives you functionality similar to :t in GHCi.
I'm not aware of any command that corresponds to :i, although I admit that it would be useful.

I recommend that you never type directly into FSI. Use an editor with F# support like Visual Studio, VS Code or Rider. Write code in the editor, select definitions or expressions in the code and send to FSI (usually with Alt-Enter). This will provide a much better experience and save you lots of time. The benefits:
Type information on hover for any symbols (including the type parameters of a function and what they might be constrained to in a particular context)
Live type-error checking over multiple functions/values
Auto-complete suggestions
Syntax highlighting
No need to put ;; at the end of any lines
I've been writing F# for several years with heavy use of FSI and after the first day I have never ever typed into FSI because there is no advantage in doing so.

Related

Haskell How to print info of some function in haskell like "ghci> :info func"

I'm new to haskell.
Sometimes I write some complicated functions that I'm not so sure about the types myself, so I don't define its type beforehand, compiling and running still work fine.
I want to know if I can print out the types of that function like in "ghci> :info someFunc" in the program, just to see how Haskell define its. Maybe something like this:
f x = 2*x
main :: IO()
main = do
print_info f
I know I can "ghci> :load program.hs" & then ":info f", but for me it is quite unconvenient & sometime working with ghci can be ugly.
Can't be done. You can sort of get close with Typeable, but polymorphism cannot be captured, even in principle.
Instead, I recommend that you set up the Haskell Language Server and connect your editor to it; most editors support at least the level of connection that lets you hover a term to see its type or add a type signature to a definition with a keybinding.

What are the rules regarding naming in Haskell?

Are there definite rules regarding naming of entities in Haskell? (by entities I mean functions, term level variables, data constructors, type variables, type constructors, typeclasses, modules; not sure if I left something out here) For example
<interactive>:1:13: error:
Not in scope: type constructor or class ‘Zed’
Perhaps you meant type variable ‘zed’ (line 1)
I know that in type signatures concrete types must be uppercase. So is it assuming that Zed is a concrete type, and because this type isn't defined (isn't in scope), we get an error?
Are there any other actual rules on naming stuff in Haskell?
As was pointed out by M. Aroosi in a comment, your errors don't match your example – you seem to have written f :: zed -> Zed : f = undefined instead, with a : instead of a ;. If you use a ; you will get one of two results. If Zed is undefined, you'll get an error telling you so:
Prelude> f :: zed -> Zed ; f = undefined
<interactive>:2:13: error:
Not in scope: type constructor or class ‘Zed’
Perhaps you meant type variable ‘zed’ (line 2)
If Zed is defined, everything will work:
Prelude> data Zed = TheZed
Prelude> f :: zed -> Zed ; f = undefined
Prelude>
The general rule for Haskell names is:
At the type level:
Type names start with an uppercase letter.
Type variables start with a lowercase letter.
At the term level:
Constructor names start with an uppercase letter if they're ordinary names.
Constructor infix operators start with a :.
Variable names start with a lowercase letter if they're ordinary names.
Variable infix operators start with anything but a :.
There are some further wrinkles (e.g., you can't use , in names; you can't have a name that's only -s and 2 or more character long), but that covers 95% of it.
You are using the REPL (Ghci). If you try to use a type signature in the REPL, you need to use :{ .....\n ..... \n ..... :} kind of multiline input. Then you can do the type signature of the function along with implementation(s) of that type signature. Its not very practical - 1 typo and you have to do it all over again. (Julia language REPL does a much better job with that, btw.).
And yes, there are style guides and types need to start with an uppercase. Usually the compiler warns/errors you.
Since you seem to start out, I suggest you use a source file for your experiments because as soon as you end up with multiple line constructs, the REPL kind of sucks. And it is really easy to use a file for your code. See :load :cd :reload etc. for your GHCI commands which support you doing that.

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 find the type of subfunctions with GHCI [duplicate]

This question already has answers here:
Can GHCi tell me the type of a local Haskell function?
(3 answers)
Closed 7 years ago.
Is it possible to find the type of functions defined in a where statement with GHCI ?
For example, considering this function :
myFunction a b c = case result of
2 -> ...
where
subFunctA = ...
_ -> ...
where
subFunctB = ...
subFunctC = ...
The type of myFunction can be find with :t myFunction.
Is it possible to find the types of subFunctA, subFuncB and subFunctC with GHCI ?
You could try using typed holes if you have a new enough version of GHCi.
Basically, if you write an underscore in the code, the compiler will spit out an error message telling you what type that subexpression should have. In your example, just replace "..." with "_".
No. GHCi does not have access to the source of its functions. This is true even if you defined the function yourself in GHCi, or in a source file.
As an alternative: since you have access to the source of the function you're wondering about, you can copy the functions into the global scope of your source file, compile them, and see what type GHC assigns them. I do this a lot. (Also, you can paste them into GHCi directly.) Once you've done this, you can call :t on them all you want. This does run the risk of producing more general types than the actual sub-functions have, but it could still help you.

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!

Resources