Monday, December 31, 2012

HASKELL GHCI "INTERACTIVE MODE"

HASKELL GHCI "INTERACTIVE MODE"




REVISED: Friday, October 11, 2024






Haskell GHCi interpreter interactive mode.


I. HASKELL GHCI INTERPRETER

We have two options for working with the GHCi interpreter.  First, we can use your favorite  editor or the Visual Studio Code (VSC) editor. Second,  we can work with the GHCi interpreter without an editor.

A. VISUAL STUDIO CODE (VSC)

If you choose to use the Visual Studio Code editor, double left mouse click the Visual Studio Code icon on your desktop. If you followed along with VSC in the previous "Downloading And Installing Haskell" tutorial you will probably remember VSC will open with a horizontally split window showing the Main.hs program at the top and the Power Shell (PS) prompt at the bottom.

VSC is asking what do you want to work with. You want "ghci" so after the " > " prompt type ghci and then press Enter.

PS C:\Users\Tinnel>ghci

VSC will respond as follows:

PS C:\Users\Tinnel> ghci
GHCi, version 9.8.1: https://www.haskell.org/ghc/  :? for help
Prelude>

When you see the Prelude> prompt you know you are in GHCi.

First, you must tell GHCi the path to your "working directory" as follows:

GHCi, version 9.8.1: https://www.haskell.org/ghc/  :? for help
Prelude> :cd c:\users\tinnel\haskell2024\newProjects\
Prelude>

Second, GHCi is asking you to load the module located in this working directory. Therefore, you would create a new module file; e.g., Pet.hs by following the directions described in the previous "Downloading And Installing Haskell" tutorial.  Then based on your module name, type something similar to the following:

ghci> :load Pet.hs
[1 of 1] Compiling Pet             ( Pet.hs, interpreted )
Ok, one module loaded.
ghci>

B. GHCi

As I said before, you have two options for working with GHCi. You can write Haskell programs using an editor; e.g., the VSC editor or you can work directly with GHCi.

Double left-click the Haskell shortcut icon you created on your desktop in the previous "Downloading And Installing Haskell" tutorial and the following will appear.

GHCi, version 9.8.1: https://www.haskell.org/ghc/  :? for help
Prelude>

The Prelude> prompt means you are in GHCi.

In the following tutorials, if I do not say what method is being used to work with GHCi we are not working with the VSC editor, we are working directly with the GHCi interpreter without an editor.

C. GHCI INTRODUCTION

GHCi is an interactive Haskell Read-Eval-Print-Loop (REPL) that comes with GHC. The Haskell GHCi interactive interpreter accepts your user input statements after the Prelude> prompt.

Haskell has referential transparency. Referentially transparent means no mutation, which means variables, data structures, everything within a particular program, is immutable or in other words unchanging over time, or unable to be changed.

In Haskell you never assign a variable, instead you bind a name to a value. All variables you use are statically bound. Therefore, you can bind functions and values to names, and use those names in statements or expressions.

D. LET

Long GHCi commands, for example input functions such as an implicit do block, often cover more than one line of code. To communicate multiple line commands to GHCi, wrap them between :{ and :}.

After the Prelude> prompt type :{ then press Enter. GHCi will respond on the next line with Prelude| after which you type your first line of Haskell code ending with pressing Enter. When you are done entering your program type :} on a line by itself then press Enter and GHCi will run your program and print the program results on the next line.

There are many ways to program an implicit do block in Haskell. One bare bones approach, is shown below. For this to work it should be hand typed, "copy paste" will result in an error message unknown command ':{'.

Prelude> :{
Prelude| let x = 12
Prelude|      y = 5
Prelude| in  x * y
Prelude| :}
60
it :: Num a => a
Prelude>  

You let a pattern or name be "equal to" or "defined as" variables in an expression.

The syntax is let <bindings>  in <expression>. The variables defined in the let expression can be used by the in expression. let begins with bindings and is followed by an expression. First x is bound to 12 and y is bound to 5. Then x is multiplied by yHaskell requires that each variable must be bound to a value.

When you are typing your Haskell program and you need white space, do not type tabs, only type spaces. As shown below indentation counts.  The x is the first name in the let expression. The y and all subsequent names in the let expression must be indented to line up with the first name in the let expression.

The let expression in the example below does not line up the x and y names in the let expression and this creates a parse error.

Prelude> :{
Prelude| let x = 12
Prelude| y = 5
Prelude| in x * y
Prelude| :}

<interactive>:23:1: parse error on input `y'
Prelude>

Never use in in a list comprehension or a non-implicit do block.

let is used three ways in Haskell.

First, as a let expression.

let name = expression in expression

A let must be used wherever an expression is used. For example, use let to define a local variable scoped over an expression:

Prelude> (let x = 0 in x^0) + 1  -- 0^0 = 1
2
it :: Num a => a
Prelude>  

Use the ^ exponent operator to use an integer as the exponent.

Use the ** exponent operator to use a floating point number as the exponent. 
  
Second, as a let statement, only inside do notation, without using in.

do statements
       let name = expression
       statements

Third, used inside of list comprehensions, without using in.

Prelude> [(x, y) | x <- [5..12], let y = 12*x]
[(5,60),(6,72),(7,84),(8,96),(9,108),(10,120),(11,132),(12,144)]
it :: (Num t, Enum t) => [(t, t)]
Prelude>

E. USING DO

Always remember long GHCi commands, as shown below, can cover more than one line when wrapped in :{ and :}.

Prelude> :{                                                        -- Must be on line by itself.
Prelude| let prRev = do {                                      -- Starts prRev function declaration.
Prelude|        inp <- getLine;                                 -- Indentation counts!
Prelude|        putStrLn $ reverse inp;                 -- Vertical alignment is a must!
Prelude| }                                              -- Ends function declaration.
Prelude| :}                                                               -- Must be on line by itself.
prRev :: IO ()
Prelude>

Prelude>prRev                                                 -- prRev function call then press Enter
Hello, World!                                                          -- Type getLine input then press Enter
!dlroW ,olleH                                                          -- prRev reverses getLine input
it :: ()
Prelude>

F. WORKING DIRECTORY

The "working directory" is the "current directory," in other words the folder that is currently open.

For example my tutorial working directory is:

C:\Users\Tinnel\Haskell2024\newProjects\

I create a new working directory for new Haskell tutorial files each year.

I change to the working directory in GHCi by using the following commands:

Prelude> :cd C:\Users\Tinnel\Haskell2024\newProjects\
Warning: changing directory causes all loaded modules to be unloaded,
because the search path has changed.
Prelude>

Then I use the following to check to make sure the path was changed correctly: 

Prelude> :show paths
current working directory:
     C:\Users\Tinnel\Haskell2024\newProjects
module import search paths:
Prelude>

II. SAVING USER DEFINED HASKELL FUNCTIONS

Create the following file in your text editor and save it as fun1.hs:

-- My first Haskell function!
doubleX x = x + x

Notice the fun1.hs "file type" extension is hs; and there has to be a period . between the "file name" and the "file type." The file you just created can also be referred to as a "Haskell script."

Next use the :load command, as shown below, to load the Haskell script into GHCi:

Prelude> :load fun1
[1 of 1] Compiling Main             ( fun1.hs, interpreted )
Ok, 1 module loaded.
*Main>   

Notice ghci uses Main; however, our script fun1 does not contain a Main.  A Haskell program needs to have an “entry point” called main.  If your script does not contain a Main ghci will create one as it has for our script fun1.

We will call our function doubleX and have it process the number 2 as follows:

*Main>  doubleX 2
4
it :: Num a => a
*Main>

(The it :: Num a => a line of code is a "function signature." Function signatures will be discussed in detail in the "Haskell Functions Introduction" tutorial.)

Congratulations, you have just written your first Haskell function!

III. HASKELL INTERACTIVE FEEDBACK LOOP

WinGHCi was a GUI to run GHCi on Windows. Currently, there is no installation program for WinGHCi.  To start Haskell double left mouse click the Haskell icon you created on your desktop.  A window similar to the following will open:

GHCi, version 9.8.1: https://www.haskell.org/ghc/  :? for help
Prelude> 

Notice you have selected GHCi and the window you opened has a black background and the title GHCi. Before the update Windows users could select WinGHCi and open a window with a white background and the title WinGHCi at the top. Unless I find an installation program for WinGHCi I will be using GHCi throughout this tutorial series. 

Haskell code can be run interactively, or compiled to an executable. The runtime system interprets the byte-code created when the Haskell source code is processed by GHCi. 

The Haskell program we created above contains the Haskell function doubleX. Haskell, functions are called by writing the function name, a space, and then the arguments, separated by spaces. 

After the Prelude> prompt, type either :load or  :l (colon followed by the lower case letter "l") followed by the file name fun1, and then press Enter. After your input you should see the following response.

Prelude> :load fun1
[1 of 1] Compiling Main             ( fun1.hs, interpreted )
Ok, 1 module loaded.
*Main

After the Prelude> prompt, type doubleX 10, and press Enter. After your input you should see the following response.

Prelude> doubleX 10
20
it :: Num a => a
*Main

If you want to change the function, type :edit after the Prelude> prompt and press Enter. The fun1.hs file will be opened by Haskell using the Notepad editor and you can make changes and save the file.

Prelude> :edit
Ok, 1 module loaded.
*Main>

Comments are notes you embed in your program to help you remember why you coded the program the way you did. Start single-line comments with "--" (two dashes). Start multiple line comments with "{-" and end them with "-}". Haskell will not print your comments. 

Now you have an interactive feedback loop. You can change functions in the fun1.hs script, and reload the script into Haskell GHCi using :load fun1; or using :r which is equivalent because it reloads the current script.

To exit Haskell GHCi type :q to quit then press Enter.

IV. CONCLUSION

In this tutorial, you have received an introduction to the GHCI interpreter.

V. REFERENCES

Bird, R. (2015). Thinking Functionally with Haskell. Cambridge, England: Cambridge University Press.

Davie, A. (1992). Introduction to Functional Programming Systems Using Haskell. Cambridge, England: Cambridge University Press.

Goerzen, J. & O'Sullivan, B. &  Stewart, D. (2008). Real World Haskell. Sebastopol, CA: O'Reilly Media, Inc.

Hutton, G. (2007). Programming in Haskell. New York: Cambridge University Press.

Lipovača, M. (2011). Learn You a Haskell for Great Good!: A Beginner's Guide. San Francisco, CA: No Starch Press, Inc.

Thompson, S. (2011). The Craft of Functional Programming. Edinburgh Gate, Harlow, England: Pearson Education Limited.