Sunday, January 27, 2013

HASKELL FUNCTIONS INTRODUCTION

HASKELL FUNCTIONS INTRODUCTION

REVISED: Thursday, October 17, 2024




In this tutorial, you will receive an introduction to Haskell functions.

I.  FUNCTIONS

A function is a rule that assigns another number to each number in its domain. The domain consists of all numbers for which the rule makes sense. A function takes one input value and produces one output value. A function maps a domain to a range. Examples comparing math functions to their Haskell functions are as follows:

MATH             HASKELL
f ( x )                f x
f ( x, y )            f x y
f ( g ( x ) )        f (g x)
f ( x, g ( y ) )    f x (g y)
f ( x )  g ( y )    f x * g y

II.  HASKELL FUNCTIONS

Functions are used to model and solve problems. Functions should comply with the "Abstraction Principle" which says nothing should be duplicated or in other words do not repeat yourself. We want to abstract out the commonality in our programs so we do not repeat our code. This pattern of spotting a repeated idiom, and then abstracting it so we can reuse and write less code, is a common aspect of Haskell programming.

The syntax for a Haskell function definition is the function name, argument names, an equal sign, and then the function's body. The body of the function can also be thought of as an expression. Function arguments are values passed from the left side of the equal sign to parameters used within the body of the function on the right side of the equal sign.

funcName arg1 arg2 = param1 param2
 -- Parameter operations compute to a returned value.

Prelude>  let times x y = x * y
times :: Num a => a -> a -> a
Prelude>

Prelude>  times 2 3
6
it :: Num a => a
Prelude>

The = symbol in Haskell can be read, "The function name on the left is defined to be the expression on the right." The expression on the right explains what the function does. In the example above the function named times is defined to be the parameter expression x * y.  What does the function times do? times multiplies x by y. 

In Haskell you never assign a variable, instead you bind a name to a value.    Local variables may be bound using let, which declares a new binding for a variable with local scope.

For example, when we apply the argument values 2 and 3 to the function times, the argument variables x and y are given or "bound to" the argument values 2 and 3. When x is bound to 2 and y is bound to 3; the result is the parameter expression 2 * 3.

Regular variables, such as arguments and parameters, always begin with a lowercase letter. A Haskell parameter variable provides a way to give a name to an expression. After a parameter variable is bound to; i.e., associated with a particular expression, its value does not change.

A function is a single expression, not a sequence of statements. The value of the expression is the result of the function. A function has input and output. A function describes how to produce the output from its input. Each Haskell function has a single result. The right hand side is equal to the left hand side in the sense that it might be substituted for it anywhere in the program.

In Haskell, a predicate is a function that returns a Boolean value. It is used to test whether a value satisfies a certain condition. For example, the following predicate checks if a number is even:

even :: Int -> Bool
even n = n `mod` 2 == 0

ghci> even 8
True

A. FUNCTION SIGNATURE

Haskell does not require function signatures; however, when you become an experienced Haskell programmer your first step, when you write a Haskell function, will be to write the function's signature. The signature declares the types of the arguments and the type of the result. Signatures are self documenting. 

times :: Num a => a -> a -> a

The operator :: is pronounced ''has type", and it separates the name of the function from the type definitions. The left side of the :: operator is in the "value namespace," and the right side of the :: operator is in the "type namespace." If there are more than one function input parameter, each parameter is separated from the next parameter by a -> kleisli arrow representing a morphism. The type of the last input parameter in the list, is the type of the output of the function. And, a morphism is just a systematic way of turning solutions of one system into solutions of another.

It is common Haskell practice to keep the names of type variables very short. One letter is common. Long names are rarely used. Type signatures are usually brief. We gain more in readability by keeping names short, than we would by making them descriptive.

Prelude> z (x,y) = (y,x)  -- Notice the position reversal of the arguments and parameters.

Prelude> z (12,21)

(21,12)

Prelude> :t z               
-- :t asks ghci for the type of z
z :: (b, a) -> (a, b)         -- Notice the position reversal in the type  signature.
Prelude>

B. FUNCTION BODY

The second step in writing a Haskell function is writing the body of the function, an expression, which is the function definition. In the example below the body of the function is everything to the right of the equal sign; i.e., x * y. The body of a function evaluates to a value which is returned by the function. 

times x y = x * y

Functions are defined and called in a similar manner. When a function is "defined", the function name is followed by arguments separated by spaces, an = sign read as "is", and a definition of what the function does. When a function is "called", the function name is followed by arguments separated by spaces.

In GHCI we can use the let keyword to define a function. Coding let times x y = x * y inside GHCI is the equivalent of writing times x y = x * y in a script and then loading it.

For example:

C. SCRIPT

First, "Copy Paste" the following Haskell script into your text editor; and "File, Save As" times.hs to your working directory.

-- Example of a Script
times :: Num a => a -> a -> a
times x y = x * y

Second, change to your working directory in GHCi. I used the following commands:


Prelude> :cd C:\Users\Tinnel\Haskell2024\newProjects\
Prelude>

Third, until you are comfortable with the GHCi interpreter, 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>

Fourth, load the script into the Haskell GHCi "interactive mode" as follows:

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

Fifth, call the function times and have it process the numbers 2 3 as follows:

*Main>  times 2 3
6
it :: Num a => a
*Main>  

D. INTERPRETER

Prelude> let times x y = x * y
times :: Num a => a -> a
Prelude>

Prelude> times 2 3
6
it :: Num a => a
Prelude>

Prelude> :type times
times :: Num a => a -> a -> a
Prelude>

Haskell does not require that a value or function be declared or defined in a source file script before it is used. It is perfectly normal for a definition to come after the first place it is used.

III.  HASKELL PURE FUNCTIONS

Pure code is code that does no input or output (IO) it is code outside of the IO monad.

Safe Haskell pure functions are a subset of modern Haskell that provide type safety, referential transparency, strict module encapsulation, modular reasoning and semantic consistency.

A function is pure when it has no side effects. Having no side effects means a function does not alter a state or mutate any data.

Variables are used in a computer program to store data. Each variable has its own computer memory storage location. The program's state, at any given point in the program's execution, is the contents of these memory locations.

Mutate is the act or process of being altered or changed.

Haskell functions have values that are manipulated; however, the values cannot be changed in-place. Instead of mutating the state of objects, Haskell functions return a new object with the changes we want. All Haskell functions simply receive values and produce new values. A function called twice with the same arguments will always produce the same result. This is called referential transparency.

IV. HASKELL IMPURE FUNCTIONS

Impure code is code that does input or output (IO), it is code inside the IO monad. For example, the IO can be different each time evaluated; however, the IO instructions evaluated are always the same.

V.  HASKELL INFIX FUNCTION VERSUS PREFIX FUNCTION

In infix form, an operator appears between its operands. In prefix form, the operator is enclosed in parentheses and precedes its arguments.

The - operator is Haskell's only unary operator, and we cannot mix it with infix operators. If we want to use the unary minus near an infix operator, we must wrap the expression it applies to in parentheses.

Infix functions are ones that are composed of symbols, rather than letters. For instance; +, *, and ++ are all infix functions. You can use them in non-infix mode by enclosing them in parentheses. Enclosing them in parentheses converts them into curried functions

The infix function * is a function that takes two numbers and multiplies them. We call * by placing it between numbers.

Prelude> :type (*)
(*) :: Num a => a -> a -> a
Prelude>

The function signature shown above states * is a function which, for some type a which is an instance of Num, takes a value of type a and produces another function which takes a value of type a and produces a value of type a.

In the (*) function signature Num a is a class constraint; Num is the name of the class and a is a type name. The function signature can be read for any type a that is an instance of the class Num of numeric types, function (*) has type a -> a -> a.  A type that has one or more class constraints is referred to as being overloaded.  The => operator indicates a class constraint. Most of the numeric functions in Prelude are overloaded.

`Backticks` make a function name into an infix operator.

Prelude> :type (++)
(++) :: [a] -> [a] -> [a]
Prelude>

The type of ++ means that for a given type a, ++ takes two lists of a's and produces a new list of a's.

Most functions that are not used with numbers are prefix functionsPrefix functions; for example, map, can be made infix by enclosing them in backquotes (the ticks on the tilde key on American keyboards).

VI. FUNCTION APPLICATION

Function application is "calling" a function. We call a function by typing the function name followed by a space and then the function's arguments each separated by a space followed by Enter. Function application has the strongest binding power or highest precedence, higher than all other operators.

VII. FUNCTION COMPOSITION

Function composition is the act of pipelining the result of one function, to the input of another, creating an entirely new function. This can be done with any two functions, where the argument type of the first is the return type of the second.

The dot . is the function composition operator. dot . is read as "after". The dot . operator has very high precedence, surpassed only by function application.

A. PIPELINING FUNCTIONS

Prelude>  :type (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
Prelude>

Prelude>  :info (.)
(.) :: (b -> c) -> (a -> b) -> a -> c -- Defined in `GHC.Base'
infixr 9 .          -- infix operator, right associative, precedence 9.
Prelude>  

As shown below we can pipeline the results of function y into function x and create a new function z by using the dot function composition operator.

Prelude> y = sqrt
Prelude> y 16
4.0


Prelude> x = negate
Prelude> x 4.0
-4.0


Prelude> z = x.y  -- negate.sqrt  

Prelude> z 16      -- From right to left, first sqrt of 16, then negate 4.    
-4.0
Prelude>


B. NESTING FUNCTIONS

Function composition can also be described as the nesting of two or more functions to form a single new function.

Prelude> [ x | x <- [1..10] ]
[1,2,3,4,5,6,7,8,9,10]
it :: (Num t, Enum t) => [t]
Prelude>

The symbols | and <- are read as “such that” and “is drawn from” respectively, and the expression x <- [1. .10] is called a generator.

Functions can be passed to other functions. Function composition is clear and concise and often used to make functions pass to other functions.

As shown below the same problem can be solved using Haskell script source code.

module WIP where
wip = print [x | x <- [1..10]]

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

*WIP>  wip
[1,2,3,4,5,6,7,8,9,10]
*WIP>  

VIII. CURRYING

Prelude> :type curry
curry :: ((a, b) -> c) -> a -> b -> c
Prelude> 

Prelude> :type uncurry
uncurry :: (a -> b -> c) -> (a, b) -> c
Prelude> 

Currying changes a function that takes more than one argument into a function that takes one argument. If another argument is needed, currying can be used to return another function.

All functions in Haskell take a single argument. Therefore, all functions in Haskell are considered curried; one argument in, one result out.

Prelude> (2^) 5  -- Notice there is no space between 2 and ^.  2*2*2*2*2 = 32.
32
it :: Num a => a
Prelude>

Prelude> 2^ 5
32
it :: Num a => a


Prelude>
Prelude> (^2) 5  -- Notice there is no space between ^ and 2.  5*5 = 25.
25
it :: Num a => a
Prelude>

Prelude> 5 ^2
25
it :: Num a => a
Prelude>

Note the difference between (2^), which is a function that takes a number and returns 2 to that power, and (^2), which is a function that takes a number and squares it. Currying is the process of applying a multi-argument function to one argument and producing a new function that uses the remaining arguments.

An uncurried function is a function which cannot be applied to the arguments one at a time.

IX. EXPONENT

f(x,y) = x y

f(x,y) = x -y for negative exponents calculate the positive exponent y then take the reciprocal 1/(y).

f x y = 1/(x ^ y)

Haskell has three exponentiation operators: (^), (^^) and (**).

(^) is for non-negative integral exponentiation.

(^^) is for either positive or negative integer exponentiation.

(**) is for either positive or negative floating point exponentiation.

Prelude>  :type (^)
(^) :: (Num a, Integral b) => a -> b -> a
Prelude>

Prelude>  let f x = 2^ x
Prelude>

Prelude>  f 5     -- 2*2*2*2*2 = 32.
32
Prelude>

Prelude>  :type (^^)
(^^) :: (Integral b, Fractional a) => a -> b -> a
Prelude>

Prelude>  let f x = 2^^ x
Prelude>

Prelude>  f 5
32.0
Prelude>

Prelude>  f (-5)  -- The reciprocal of 32 is 1/32 = 3.125e-2 = .03125
3.125e-2
Prelude>

Prelude>  :type (**)
(**) :: Floating a => a -> a -> a
Prelude>  

Prelude>  let f x = 2** x
Prelude>

Prelude>  f 5
32.0
Prelude>

Prelude>  f (-5)
3.125e-2
Prelude>

X. SQUARE ROOT

The square root of a number is the value of power 1/2 of that number.

f(x,y) = x 1/y = y√x1 = y√x

As shown above, in mathematics the radical sign symbol √ is placed before a number x to indicate the extraction of a root y, especially a square root y = 2. 

For square root let y equal 2 then f(x,2) = x 1/2 = 2√x1 = 2√x = √x

Prelude>  f 25  -- x = 25
5.0
Prelude>

Or, since sqrt is part of Prelude you do not have to import anything, you can just use the Haskell sqrt keyword to get the square root.

Prelude>  sqrt 25
5.0
it :: Floating a => a
Prelude>

Prelude>  :type sqrt
sqrt :: Floating a => a -> a
Prelude>  

XI. MAIN

GHC looks for a module named Main to find the main action. Therefore, each Haskell program needs to have one function named main.  The function main is the starting and ending point for every Haskell program. If you omit a module header on a Haskell file, the module name defaults to main.

The execution of a Haskell program is an evaluation of the symbol main to which we have bound an IO action. main must have type IO a where a may be any return value. If something has type IO a, then it is executable. If something does not have type IO a, then it is not executable.

XII. CONCLUSION

In this tutorial, you have received an introduction to Haskell functions.

XIII. 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.





Wednesday, January 2, 2013

HASKELL GHC "COMPILER MODE"

HASKELL GHCI "COMPILER MODE"



REVISED: Tuesday, September 24, 2024




The Glasgow Haskell Compiler (GHC).

I. WRITING YOUR FIRST HASKELL COMPILED PROGRAM

GHC is written in Haskell and is a single program which is run with different options to provide two modes of operation: GHCi (the interactive Haskell interpreter mode) and GHC (the batch compiler mode).

A. WRITE A HASKELL PROGRAM

"Copy Paste" the following Haskell program script into your text editor:

main = putStrLn "Hello, World!"

From your text editor, do a "File Save As" and save the above Haskell program, using the file name hello.hs to your working directory.  Using my text editor I saved my hello.hs file using the following working directory path:

C:\Users\Tinnel\Haskell2024\newProjects\

B. LOAD HASKELL PROGRAM INTO GHCI INTERPRETER

"Double left mouse click" the Haskell icon on your desktop to start Haskell GHCi.  A Haskell GHCi window similar to the following will open:

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

Haskell code can be compiled to an executable, or run interactively. The GHCi runtime system interprets the byte-code compiled from the source code

After the above Haskell GHCi window Prelude> prompt, type :load hello, and then press Enter. You should now see the following response:

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


You can now call the function main as follows:

*Main>  main
Hello, World!
*Main>  

You are now in the Haskell GHCi "interactive mode". You have an interactive feedback loop. Each time you change the Haskell program in the hello.hs file, you must reload it in Haskell using :load hello or :reload before you call the function main. You can make as many changes as you want to your program and interactively interpret the Haskell program until you are satisfied with your work and you are ready to compile your finished Haskell program.

C. COMPILE HASKELL PROGRAM USING GHC COMPILER

After the above Haskell GHCi window *Main> prompt, type :! ghc --make "hello", and then press Enter. You should now see the following response:

Prelude> :! ghc --make "hello"
[1 of 1] Compiling Main             ( hello.hs, hello.o )
Linking hello.exe ...
Prelude>

Congratulations, you just compiled your first Haskell program!

Examine your working directory and you will see it now contains the following files:

hello.hs      Haskell source file.
hello.o        Haskell object file.
hello.hi       Haskell interface file.
hello.exe     Haskell executable file.

GHC compiled the source file hello.hs, producing an object file hello.o and an interface file hello.hi, and then it linked the object file to the libraries that come with GHC to produce an executable called hello on Unix/Linux/Mac, or hello.exe on Windows.

II. EXECUTING YOUR FIRST HASKELL COMPILED PROGRAM

Open your "Windows Command Prompt." In Windows this will be a window with the title "Command Prompt." This window has a black background and displays white letters and when you open it, it will display something similar to the following:

C:\Users\Tinnel>

After the > prompt finish typing in your working directory path and then the hello.exe file name as shown below, and press Enter:

C:\Users\Tinnel>Haskell2024\newProjects\hello.exe
Hello, World!

C:\Users\Tinnel>

As shown above, your compiled Haskell program was executed and Hello, World! was displayed on your "Windows Command Prompt" window.

Congratulations, you have just executed your first compiled Haskell program!

Haskell programmers believe in the motto “compile early, compile often.” Live by this motto and your Haskell life will be fun and exciting!

III. REVISING A HASKELL COMPILED PROGRAM

You can revise the source file of your program as often as you like.

GHCi automatically detects if a script source file has been changed and will only reload, and or, recompile a source file if GHCi determines it is necessary to do so.

When you are done with your revisions use the following commands to ask GHCi if it is necessary to reload or recompile your source code:

A. RELOAD

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

B. RECOMPILE

Prelude> :! ghc --make "hello"
Prelude>

C.  VIEW REVISION

Open your "Windows Command Prompt" and follow the above directions in section "II. EXECUTING YOUR FIRST HASKELL COMPILED PROGRAM."

IV. CONCLUSION

In this tutorial, you have been introduced to the Glasgow Haskell Compiler (GHC) "compiler mode."

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.

Monday, December 31, 2012

HASKELL GHCI "INTERACTIVE MODE"

HASKELL GHCI "INTERACTIVE MODE"




REVISED: Tuesday, September 9, 2025






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.