Tuesday, February 12, 2013

HASKELL USER-DEFINED FUNCTIONS

HASKELL USER-DEFINED FUNCTIONS

REVISED: Wednesday, February 7, 2024




Haskell user defined functions.

I.  HASKELL USER-DEFINED FUNCTIONS

A function in Haskell is really a function, just as mathematicians intended it to be. A function is called higher-order if it takes a function as an argument or returns a function as a result. Functions are just another kind of data; therefore, it is legal to return functions as the return value from other functions. In a functional language everything, even a program, is a function. Arity is the number of arguments a function can take.

The syntax of a function definition is function name followed by argument names, then an equal sign, and an expression. In Haskell function and variable names always start with a lowercase letter. For example:

f(x) = x²

Using the Haskell Prelude interpreter the above function becomes:

Prelude>  let f x = x ^ 2  -- Function name is f, argument is x, expression is x ^ 2.
Prelude>

Prelude>  f 4  -- Function application; i.e., calling the function (4 * 4).
16
Prelude>

Prelude>  f 3  -- Function name, space, arguments calls the function (3 * 3).
9
Prelude>  

Prelude>  :type f  -- To obtain the function type; i.e., signature.
f :: Integral b => b -> b  -- Function signature.
Prelude>  

A.  COMPOSITION OR COMBINATION OPERATOR

Applying a function to the result of another function is called function composition. The composition or combination operator (.) takes two functions and combines them. The (.) function is right associative, so we work from right to left. Using the combination operator (.) we create a function which takes the arguments of the first, and returns the return-value of the second.

Prelude> :type (.)     -- :t is the same as :type
(.) :: (b -> c) -> (a -> b) -> a -> c
Prelude>

As shown above, (.) takes two functions as its arguments. The first argument (b -> c) is a function that takes b and returns c. The second argument (a -> b) is a function that takes a and returns b.

First example:

Prelude> let muladd = addx . mulx
addmul :: Num c => c -> c
Prelude>

Computing right to left: first mulx is computed; second addx is computed using the results from mulx. Therefore, compute addx after computing mulx.

Right to left: first mulx = 6 * 6 = 36; second addx = 36 + 36 = 72. 

Prelude> let mulx x = x * x             -- Second function (a -> b) computed first, will pass its results to the first function.
mulx :: Num a => a -> a
Prelude>

Prelude> mulx 6                               -- 36 = (6 * 6) when computed alone.
36
it :: Num a => a
Prelude>

Prelude> let addx x = x + x              -- First function (b -> c) computed last.
addx :: Num a => a -> a
Prelude>  

Prelude> addx 36                             -- 72 = (36 + 36) when computed alone.
72
it :: Num a => a
Prelude>

Prelude>  muladd 6
72
it :: Num c => c
Prelude>  

Second example:

Prelude> let addmul = mulx . addx
muladd :: Num c => c -> c
Prelude>

Computing right to left: first addx is computed; second mulx is computed using the results from addx. Therefore, compute mulx after computing addx.

Right to left: first addx = 6 + 6 = 12; second mulx = 12 * 12 = 144. 

Prelude> add
mul 6
144
it :: Num c => c
Prelude>

Third example:

Prelude> filter ((<=9).(*3)) [1,2,3,4,5,6,7,8,9]
[1,2,3]

it :: (Ord b, Num b) => [b] Prelude>

Right to left: Filter out original list elements "after" first multiplying each list element by three; and then testing each result to see if it is (<= 9).

(1*3)(<=9)True
(2*3)(<=9)True
(3*3)(<=9)True
(4*3)(<=9)False
(5*3)(<=9)False
(6*3)(<=9)False
(7*3)(<=9)False
(8*3)(<=9)False
(9*3)(<=9)False


B.  INDENTATION

There is very little redundancy in Haskell so almost everything, including whitespace, has meaning.

Operator whitespace has the highest precedence and binds to the left.

Haskell recognizes blocks by indentation and newlines as separators.

Indentation matters. Top level declarations start in the first column. A declaration can be broken at any place, and continued in the next line, provided that the indent is larger than the indent of the previous line.

C.  FUNCTION NAMES

Function names can not begin with uppercase letters; and calling a function with the same arguments always returns the same value. In Haskell, there is a "main function" and every object has a type. The type of the main function is IO ( ).

Type constructors are the only functions starting with a capital letter, and the only functions that can appear on the left-hand side of an expression.

D.  FUNCTION EXAMPLE

Length is a function that counts the number of elements in a list. The :: separates the name of the function from the type definitions. The characters -> separate the different type definitions. The last type definition is the result, output, of the function while the others are parameters, input.

-- length function signature
length               :: [a] -> Integer            -- length takes a list of a, returns an Integer.
length         [ ]  = 0                                  -- Base case, empty list.
length (x : xs)  = 1 + length xs              -- Recursive case.

This definition is almost self-explanatory. length is a function that takes a list containing values of type a and gives back a value of type Integer. We can read the equations as saying: "The length of the empty list is 0, and the length of a list whose first element is x and remainder is xs is 1 plus the length of xs." Note the naming convention used here; xs is the plural of x, and should be read that way. Examples of the above length function are as follows:

Prelude> length [1, 2, 3, 4, 5]                             -- [ ] pronounced "list of" when not an empty list.
5
it :: Int
Prelude>

Prelude> length ["1", "2", "3", "4", "5"]      -- "List of" Characters.
5
it :: Int
Prelude>

Prelude> length [("1", "2"), ("3", "4")]         -- "List of" Tuples of Characters.
2
it :: Int
Prelude>

Prelude> length [["1", "2"], ["3", "4"]]         -- "List of" Character lists.
2
it :: Int
Prelude>

Prelude> length [[1, 2], [3, 4], [5, 6]]                -- "List of" Integer lists.
3
it :: Int
Prelude>

E.  CONS OPERATOR

The : operator, also called the cons operator, takes a number and a list of numbers or a character and a list of characters. The value to the left of the : is placed as the first element of the list. The process of adding an element is called "consing".

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

The cons operator : takes a value of type a and another value of type [a] list of as, and produces another value of type [a] list of as.

The cons operator associates to the right. For example, [1,2,3] is an abbreviation for 1 : (2 : (3 : [ ])).

Cons patterns must be parenthesised when defining functions, because function application has higher priority than all other operators.

F.  POLYMORPHIC FUNCTIONS

Polymorphism means that a single function can be applied to a variety of argument types. The length function is an example of a polymorphic function. It can be applied to a list containing elements of any type, for example [Integer], [Char], or [[Integer]]the caller gets to pick the type. 

G.  APPLY ($) OPERATOR

In Haskell, function application is left associative. When an argument to a function is a result of another function, you have to use parentheses.

For example:

a b (c d)

means the function a acting on two arguments, b and (c d), which itself is an application of function c to d.

The parentheses can be removed by using $ operator.

a b $ c d 

The $ function is also an operator for function application. Function application with $ is right-associative. Using $ we do not have to write as many parentheses. When a $ is encountered, the expression on its right is applied as the parameter to the function on its left. $ means that function application can be treated just like another function. For example, we can map function application over a list of functions.  

Prelude> :type ($)
($) :: (a -> b) -> a -> b
Prelude>

$ binds to the right and has the lowest precedence of any operator. The $ operator is used to leave out the closing parentheses in a Haskell statement. When you see a $ mentally replace it with a left open parentheses ( and mentally place the right closing parentheses ) at the end of the statement. Neither a $ nor a closing parentheses ) is coded at the end of the statement.

H.  TUPLES

We often use tuples to return multiple values from a function. 

A tuple is a fixed-size collection of values, where each value can have a different type. This distinguishes them from a list, which can have any length, but whose elements must all have the same type. Haskell tuples are not immutable lists.

I.  REWRITE HASKELL FUNCTIONS

One way to practice writing functions is to write your own version of existing Haskell functions. For example, sort is an existing Haskell function which can be imported as shown below.

Prelude>  import Data.List
Prelude>

Prelude>  :type sort
sort :: Ord a => [a] -> [a]
Prelude>

Prelude>  sort [1,7,2,9,5,4,3]
[1,2,3,4,5,7,9]
it :: (Ord a, Num a) => [a]
Prelude>

Your own sort might look something like the following:

module Mysort where

mysort              :: Ord a => [a] -> [a]
mysort          [] = []
mysort (x : xs) = mysort smaller ++ [x] ++ mysort larger
    where
        smaller = [a | a <- xs, a <= x ]
        larger   = [b | b <- xs, b > x ]

"Copy Paste" the above module into you text editor and "Save As" Mysort.hs to your working directory.

Load Mysort.hs into GHCi.

Prelude>  :load Mysort
[1 of 1] Compiling Mysort           ( Mysort.hs, interpreted )
Ok, modules loaded: Mysort.
Prelude>  

Call the mysort function in GHCi.

Prelude> mysort [1,7,2,9,5,4,3]
[1,2,3,4,5,7,9]
it :: (Ord a, Num a) => [a]
Prelude>

Playing and comparing your functions to the existing Haskell functions makes learning more fun. 

-- foldr.

Prelude>  :type foldr
foldr :: (a -> b -> b) -> b -> [a] -> b
Prelude>  

-- Using foldr for sum.

Prelude>  let sum xs = foldr (+) 0 xs
sum :: Num b => [b] -> b
Prelude>

Prelude>  :type sum
sum :: Num b => [b] -> b
Prelude>

Prelude>  sum [1,2]
3
it :: Num b => b
Prelude>  

Prelude>  let mysum = foldr (+) 0
mysum :: Num b => [b] -> b
Prelude>

Prelude>  :type mysum
mysum :: Num b => [b] -> b
Prelude>

Prelude>  mysum [1,2]
3
it :: Num b => b
Prelude> 

-- Using foldr for product.

Prelude>  let product xs = foldr (*) 1 xs
product :: Num b => [b] -> b
Prelude>

Prelude>  :type product
product :: Num b => [b] -> b
Prelude>

Prelude>  product [1,2]
2
it :: Num b => b
Prelude>  

Prelude>  let myproduct = foldr (*) 1
myproduct :: Num b => [b] -> b
Prelude>

Prelude>  :type myproduct
myproduct :: Num b => [b] -> b
Prelude>

Prelude>  myproduct [1,2]
2
it :: Num b => b
Prelude> 

-- Using foldr for concat.

Prelude>  let concat xs = foldr (++) [] xs
concat :: [[a]] -> [a]
Prelude>

Prelude>  :type concat
concat :: [[a]] -> [a]
Prelude>

Prelude>  concat [['a','b'],['c','d']]
"abcd"
it :: [Char]
Prelude>  

Prelude>  let myconcat = foldr (++) []
myconcat :: [[a]] -> [a]
Prelude>

Prelude>  :type myconcat
myconcat :: [[a]] -> [a]
Prelude>

Prelude>  myconcat [['a','b'],['c','d']]
"abcd"
it :: [Char]
Prelude>  

J.  MAKE UP YOUR OWN FUNCTIONS

Prelude>  let search xs y = [i | (i,x) <- zip [0..] xs, x==y]
search :: (Num t, Eq a, Enum t) => [a] -> a -> [t]
Prelude>

Prelude>  :type search
search :: (Enum t, Eq a, Num t) => [a] -> a -> [t]
Prelude>

Prelude>  search "bookshop" 'o'
[1,2,6]
it :: (Num t, Enum t) => [t]
Prelude>  

Module:

module MyRepeat where

myRepeat :: a -> [a]
myRepeat x = x:myRepeat x  -- This is an infinite loop.

GHCi:

Prelude>  :load MyRepeat
[1 of 1] Compiling MyRepeat               ( MyRepeat.hs, interpreted )
Ok, modules loaded: MyRepeat.
Prelude> 

Prelude>  take 10 $ myRepeat 5  -- Used take function to prevent infinite loop.
[5,5,5,5,5,5,5,5,5,5]
Prelude>

The take function has two arguments. The first argument is the number of elements that will be taken; i.e., 10. The second argument is the list of elements the selection will be made from, in the above case an infinite list of 5s.

The function signature for take is:

take :: Int -> [a] -> [a]

Using the $ is the same as typing:

take 10 (myRepeat 5)

K.  SEE HOW MANY DIFFERENT WAYS YOU CAN WRITE THE SAME FUNCTION

-- The function f yields a sum of positive squares.

module F where

f      :: (Num a, Ord a) => [a] -> a
f xs = sum [ x*x | x <- xs, x > 0 ]

"Copy Paste" the module F shown above to your text editor and "Save As" F.hs in your working directory.

Load the module F into GHCi as shown below:

Prelude>  :load F
[1 of 1] Compiling F             ( F.hs, interpreted )
Ok, modules loaded: F.
Prelude>  

Call the function f as follows:

Prelude>  f [1,2,3]  -- sum == 1 + 4 + 9 == 14
14
it :: (Ord a, Num a) => a
Prelude>

Alternatively you can use let as shown below:

Prelude>  let f xs = sum [ x*x | x <- xs, x >0 ]
f :: (Ord b, Num b) => [b] -> b
Prelude>

Prelude>  :type f
f :: (Ord b, Num b) => [b] -> b
Prelude>
Prelude>  f [1,2,3]
14
it :: (Ord b, Num b) => b
Prelude>  

-- The function f1 yields a sum of positive squares.

module F1 where

f1      :: (Num b, Ord b) => [b] -> b
f1 xs = foldr add 0 (map square (filter positive xs))
   where
   add x y     = x + y
   square x   = x * x
   positive x = x > 0

"Copy Paste" the module F1 shown above to your text editor and "Save As" F1.hs in your working directory.

Load the module F1 into GHCi as shown below:

Prelude>  :load F1
[1 of 1] Compiling F1               ( F1.hs, interpreted )
Ok, modules loaded: F1.
Prelude>  

Call function f1 as shown below:

Prelude>  :type f1
f1 :: (Num b, Ord b) => [b] -> b
Prelude>

Prelude>  f1 [1,2,3]     -- (1*1) + (2*2) + (3*3) = 14
14
it :: (Ord b, Num b) => b
Prelude>  

II.  CONCLUSION

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

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



Sunday, February 10, 2013

HASKELL LAMBDA CALCULUS

HASKELL LAMBDA CALCULUS


REVISED: Saturday, February 10, 2024




Haskell Lambda Calculus.

I.  HASKELL LAMBDA CALCULUS

Introduced by Alonzo Church in the 1930s, Lambda Calculus, consisting of a single transformation rule and function definition scheme, is the world's smallest programming language. Any computable function can be expressed and evaluated using Lambda Calculus.

A. LAMBDA CALCULUS WITH ONE VALUE

λx.x*x

Rewriting the above Lambda Calculus equation into a Haskell anonymous function only requires three steps.

Firstly, give the equation a name followed by an = sign.

Secondly, replace the λ with a backslash \. λ pronounced lambda, is supposed to resemble the Greek λ lambda without the hook.

Thirdly, replace the . with an arrow ->.

As shown below, λx.x*x becomes square = \x -> x*x:

module Square where                       -- "File, Save As" Square.hs
square :: Num a => a -> a                  -- Type signature.
square = \x -> x*x                             

"Copy, Paste" the Square module shown above into your text editor and "File, Save As" Square.hs in your working directory.

An explicitly declared type, as shown above for square, is called a type signature. The type signature says square is a function which, for some type a which is an instance of Num, takes a value of type a and gives back a value of type a.

Load the module Square into GHCi.

Prelude> :load Square                              -- GHCi interpreter.
[1 of 1] Compiling Square           ( Square.hs, interpreted )
Ok, modules loaded: Square.

Use GHC to compile Square.

Prelude> :! ghc --make "*Square"     -- GHC compiler.
[1 of 1] Compiling Square           ( Square.hs, Square.o )

Call the square function.

Prelude> square 5                               -- Use lower case s for square.
25
it :: Num a => a
Prelude>  

To use the Lambda Calculus anonymous function in the GHCi interactive shell requires enclosing the anonymous function with parentheses as shown below:

Prelude> (\x -> x*x) 5                     
25
it :: Num a => a
Prelude>  

B. LAMBDA CALCULUS WITH TWO VALUES

Shown below is a Lambda Calculus function that takes two numbers, triples the first number and adds the result to the square of the second number.

λxλy.3*x+y*y 

Rewriting the above Lambda Calculus equation into Haskell  is shown below:

module Twoval where                         -- File "Save As" Twoval.hs
twoval = \x y -> 3*x + y*y

"Copy, Paste" the Twoval module shown above into your text editor and "File, Save As" Twoval.hs in your working directory.

Load the module Twoval into GHCi as shown below:

Prelude> :load Twoval                        -- GHCi interpreter.
[1 of 1] Compiling Twoval           ( Twoval.hs, interpreted )
Ok, modules loaded: Twoval.

Use GHC to compile Twoval.

Prelude> :! ghc --make "*Twoval"     -- GHC compiler.
[1 of 1] Compiling Twoval           ( Twoval.hs, Twoval.o )

Call the twoval function.

Prelude> twoval 2 3                       -- Use lower case t for twoval. (3*2) + (3*3) = 6 + 9 = 15.
15
it :: Integer
Prelude>  

Notice calling the Haskell anonymous function takes less work as shown below:

Prelude> (\x y -> 3*x + y*y) 2 3      -- (Parentheses required) then variables.
15
it :: Num a => a
Prelude>  

II. HASKELL LAMBDA CALCULUS ANONYMOUS FUNCTIONS

Anonymous functions are normally used to make functions that are only used once or passed to other functions.

In pure lambda calculus there are no constants. A Haskell lambda can only have a single clause in its definition.

(λxλy.6*x+y*y*y)5 2

λ notation allows us to create anonymous functions without names. Notice λ is a backward slash \ and not a forward slash / as used in division or negate.

Instead of using function names to define functions, we define them anonymously via a lambda abstraction.

Prelude> (\x y -> 6*x + y*y*y) 5 2   -- (6*5) + (2*2*2) = 30 + 8
38
it :: Num a => a
Prelude> 

Prelude> map (\ar -> ar + 3) [10,20,30,40]  -- lambda abstraction is (\ar -> ar + 3)
[13,23,33,43]
Prelude>

III.  CONCLUSION

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

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


Saturday, February 9, 2013

HASKELL SOURCE CODE EXAMPLE: READING FROM A FILE

HASKELL SOURCE CODE EXAMPLE: READING FROM A FILE

REVISED: Wednesday, January 24, 2024




Haskell source code example: Reading From A File.

I.  HASKELL SOURCE CODE EXAMPLE OF READING FROM A FILE

A. CREATE A FILE

"Copy Paste" the following paragraph into your text editor:

Mary had a little lamb,
its fleas were white as snow.
And everywhere that Mary went,
its fleas were sure to go.

From your text editor do a "File, Save As"

txtFileIn.txt

B. WRITE HASKELL PROGRAM

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

module Main where
main :: IO ()
main = do x <- readFile "txtFileIn.txt"
          putStrLn x

From your text editor do a "File, Save As

Main.hs

Notice, neither readFile nor writeFile ever provide a Handle for you to work with, so there is nothing to ever hClose.

readFile should be used instead of opening, reading, and closing a file.

C. LOAD HASKELL PROGRAM INTO GHCi INTERPRETER

After the GHCi  Prelude> prompt type :load Main as shown below, then press Enter:

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

D. COMPILE HASKELL PROGRAM

After the GHCi  Prelude> prompt type :! ghc --make "*Main" as shown below, then press Enter:

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

E. EXECUTE COMPILED HASKELL PROGRAM

Navigate to your working directory window. Hold down the Shift key and right mouse click in any open area of the window. Select the "Open command window here" option. The following path will be filled in for you:

C:\Users\Tinnel\Haskell2024>

After the > prompt type Main.exe and press Enter and the compiled program will be executed as shown below:

C:\Users\Tinnel\Haskell2024>Main.exe
Mary had a little lamb,
its fleas were white as snow.
And everywhere that Mary went,
its fleas were sure to go.

C:\Users\Tinnel\Haskell2024>

II. HASKELL GHCI INTERPRETER SOURCE CODE TO READ A FILE

A. MAIN

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

Prelude> main
Mary had a little lamb,
its fleas were white as snow.
And everywhere that Mary went,
its fleas were sure to go.
Prelude>

B. READFILE

Prelude> readFile "txtFileIn.txt"
"Mary had a little lamb,\nits fleas were white as snow.\nAnd everywhere that Mary went,\nits fleas were sure to go."
it :: String  -- Remember this prints because of "options currently set: +t"

C. :EDIT

Prelude> :edit "txtFileIn.txt"
Ok, modules loaded: Main.

The above :edit "txtFileIn.txt" code will open a Notepad window with the following displayed:

Mary had a little lamb,
its fleas were white as snow.
And everywhere that Mary went,
its fleas were sure to go.

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

In this tutorial, you have received an introduction to reading from a file.

HASKELL SOURCE CODE EXAMPLE: WRITING TO A FILE

HASKELL SOURCE CODE EXAMPLE: WRITING TO A FILE



REVISED: Saturday, February 10, 2024




Haskell SOURCE CODE EXAMPLE: Writing To A File.

I.  HASKELL SOURCE CODE EXAMPLE OF WRITING TO A FILE

When we execute a Haskell program, the "main function" of the "Main module" gets called.

A. WRITE HASKELL PROGRAM

For example; "Copy Paste" the following Haskell program into your text editor:

module Main where  -- Capital M
main :: IO ()               -- Lowercase m
main = writeFile "C:/Users/Tinnel/Haskell2024/txtFileOut.txt" oops
oops = "A hearse. A hearse. My kingdom for a hearse."

From your text editor select "FileSave As", and save the file as: 

Main.hs   -- Capital M

Notice for Windows you have to use forward slashes / and not backward slashes \ for the file path. And you can use any file path you want as long as you have system privileges for writing to files at that path location.

Both readFile and writeFile operate in text mode.

B. LOAD HASKELL PROGRAM INTO GHCi INTERPRETER

After the GHCi  Prelude> prompt type :load Main as shown below, then press Enter:

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

C. COMPILE HASKELL PROGRAM

After the GHCi  Prelude> prompt type :! ghc --make "*Main" as shown below, then press Enter to compile the program:

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

D. EXECUTE COMPILED HASKELL PROGRAM

Navigate to your working directory. C:/Users/Tinnel/Haskell2024/ is my working directory. From your working directory, hold down the Shift key and right mouse click in any open area of the window. Select the "Open command window here" option. The following path will be filled in for you:

C:/Users/Tinnel/Haskell2024>

NOTE: You must have sufficient operating system privilege in the directory and folder you want to use to perform this operation! On my computer I used the path C:/Users/Tinnel/Haskell2024/ which is where I have system privilege to write to files.

On Windows 8, from the desktop, hover your mouse over the lower left corner until the start box appears and right click. Select “Command Prompt (Admin)”.

As shown below, after the > prompt type Main.exe and press Enter and the compiled program will be executed:

C:/Users/Tinnel/Haskell2024>Main.exe  -- Writes to file not the screen!

C:/Users/Tinnel/Haskell2024>

E. READ FILE

From your text editor, open  C:/Users/Tinnel/Haskell2024/txtFileOut.txt and you will see the following:

A hearse. A hearse. My kingdom for a hearse.

Congratulations! You have written to a file!

II. CONCLUSION

In this tutorial, you have received an introduction to writing to a file.

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



Tuesday, February 5, 2013

HASKELL MODULES

HASKELL MODULES



REVISED: Tuesday, October 22, 2024




Haskell Modules.

I. HASKELL MODULES

Modules are a software design technique that allows you to group together related code.

A. HASKELL MAIN MODULE

A Haskell program is a collection of modules, one of which, by convention, must be called Main and must export the value main.

Module names are alphanumeric and must begin with a capital letter. For most modules, the module name must match the file name which must also begin with a capital letter. If it does not, GHCi might not be able to find it.

An I/O action will be performed when we give a module name or file name a name of Main and then run that Main module name or file name. For example:

Prelude> :load Main
[1 of 1] Compiling Main ( main.hs, interpreted ), modules loaded: Main.
Prelude>

B. IMPORTING HASKELL MODULES

Modules can be imported into GHCi using the keyword import as shown below:

Prelude> import System.Environment
Prelude>

Prelude> import System.IO
Prelude>

Prelude> import Test.QuickCheck
Prelude>

Prelude> :show imports
import Prelude   -- always implicitly available
import System.Environment
import System.IO
import Test.QuickCheck
Prelude>

Modules can also be imported into GHCi using :module + as shown below:

Prelude> :module +Text.Printf 
Prelude>

Prelude> :show imports
import Prelude   -- implicit
import System.Environment
import System.IO
import Text.Printf
import Test.QuickCheck
Prelude>

After a module has been imported you can use :browse to browse all of its function type signatures. For example:

Prelude> :browse Text.Printf
data FieldFormat
  = FieldFormat {fmtWidth :: Maybe Int,
                 fmtPrecision :: Maybe Int,
                 fmtAdjust :: Maybe FormatAdjustment,
                 fmtSign :: Maybe FormatSign,
                 fmtAlternate :: Bool,
                 fmtModifiers :: String,
                 fmtChar :: Char}
type FieldFormatter = FieldFormat -> ShowS
data FormatAdjustment = LeftAdjust | ZeroPad
data FormatParse
  = FormatParse {fpModifiers :: String,
                 fpChar :: Char,
                 fpRest :: String}
data FormatSign = SignPlus | SignSpace
class HPrintfType t where
  Text.Printf.hspr :: Handle -> String -> [Text.Printf.UPrintf] -> t
class IsChar c where
  toChar :: c -> Char
  fromChar :: Char -> c
type ModifierParser = String -> FormatParse
class PrintfArg a where
  formatArg :: a -> FieldFormatter
  parseFormat :: a -> ModifierParser
class PrintfType t where
  Text.Printf.spr :: String -> [Text.Printf.UPrintf] -> t
errorBadArgument :: a
errorBadFormat :: Char -> a
errorMissingArgument :: a
errorShortFormat :: a
formatChar :: Char -> FieldFormatter
formatInt :: (Integral a, Bounded a) => a -> FieldFormatter
formatInteger :: Integer -> FieldFormatter
formatRealFloat :: RealFloat a => a -> FieldFormatter
formatString :: IsChar a => [a] -> FieldFormatter
hPrintf :: HPrintfType r => Handle -> String -> r
perror :: String -> a
printf :: PrintfType r => String -> r
vFmt :: Char -> FieldFormat -> FieldFormat
Prelude> 

C. UNLOADING HASKELL MODULES

Modules can also be unload from GHCi by using :module - as shown below:

Prelude> :module -System.IO
Prelude>

Prelude> :show imports
import Prelude   -- implicit
import System.Environment
import Test.QuickCheck
import Text.Printf
Prelude>

II. MODULE SKELETON

-- MODULE DECLARATION
module Main where
-- Main is the name of module declaration, always capitalize the module name's first letter.

-- IMPORTS
import Data.List ()
import System.IO ()

-- MAIN PROGRAM
main :: IO ()
main = putStrLn "Hello, world!"  -- Notice main starts with lowercase m

-- FUNCTIONS

Any import directives must appear in a group at the beginning of a module. They must appear after the module declaration shown above, but before all other code. We cannot, for example, scatter them throughout a source file.

III. WRITING YOUR FIRST HASKELL MODULE

If we want to do some serious programming, it is very likely that our program will increase in size. An overview of a lengthy file is a difficult task. Therefore, long projects are divided into parts, containing pieces of a program that belong together. These parts are called modules.

A Haskell module can be typed into a text file that you can edit. You can use any text editor with an understanding of code and indentation; e.g., Notepad++, to type a Haskell module or as previously mentioned Visual Studio Code.

First, "Copy Paste" the following module example into your text editor and "File Save As" Factorial.hs into your working directory.

-- My first Haskell module!
module Factorial where

factorial :: (Eq a, Num a) => a -> a
factorial 0 = 1                                  -- Base case.
factorial n = n * factorial (n-1)         -- Recursive case.

The factorial type signature shown above defines a generic type signature which creates a function that works for several types. The compiler will infer the actual types using type inference.

Second, load Factorial.hs into GHCi as follows:

Prelude> :load Factorial
[1 of 1] Compiling Factorial        ( Factorial.hs, interpreted )
Ok, modules loaded: Factorial.
Prelude>

Third, call the factorial function as follows:

Prelude> factorial 3     -- Notice that the f in factorial is lowercase!
6
it :: (Num a, Eq a) => a
Prelude>

Fourth, let's look at what happens when you execute factorial 3:

3 isn't 0, so we calculate the factorial of 2
     2 isn't 0, so we calculate the factorial of 1
          1 isn't 0, so we calculate the factorial of 0
               0 is 0, so we return 1.
          To complete the calculation for factorial 3, we multiply the current number, 1, by the   factorial of 0, which is 1, obtaining 1 = (1 × 1).
     To complete the calculation for factorial 3, we multiply the current number, 2, by the factorial of 1, which is 1, obtaining 2 = (2 × 1 × 1).
To complete the calculation for factorial 3, we multiply the current number, 3, by the factorial of 2, which is 2, obtaining 6 = (3 × 2 × 1 × 1).


Recursion is analogous to the concept of induction in mathematics.

We can see how the result of the recursive call is calculated first, then combined using multiplication.

Factorial takes a single non-negative integer as an argument, finds all the positive integers less than or equal to "n", and multiplies them all together.

The factorial of any number is just that number multiplied by the factorial of the number one less than it. There is one exception to this. If we ask for the factorial of 0, we do not want to multiply 0 by the factorial of -1. In fact, we just say the factorial of 0 is 1. We define it to be so. So, 0 is the base case for the recursion. When we get to 0 we can immediately say that the answer is 1, without using recursion.

3*2*1*1 = 6   -- The last 1 is the factorial of zero.

For modularization of our own definitions; put exactly one module in a single file. Give the same names to files and modules. Thus the example above is saved as Factorial.hs.

Since the module name must begin with a capital letter, the file name must also start with a capital letter.

A. SAVING TO ANY DIRECTORY OR FOLDER

You can save Factorial.hs anywhere you like, but if you save it somewhere other than your working directory you will need to change to that directory in GHCi:

Prelude> :cd dir
Prelude>

Where dir is the directory (or folder) in which you saved Factorial.hs.

To load a Haskell module into GHCi, use the import command:

Prelude> import Factorial 
Prelude>

Congratulations, you have just written your first Haskell module!

IV. COMBINING HASKELL FILES INTO PROJECTS

Each module must import all modules containing functions used within its definitions. Usually, some functions will be shared among all modules. In this case, each module must import the module where the function is defined. Modularization is beneficial in functional programming for several reasons. Program units get smaller and easier to manage. Control over connections among various modules is transparent for future use and error detecting. A number of files can be loaded in a convenient way by loading the project file only.

V. CONCLUSION

In this tutorial, you have been introduced to the importance of using Haskell modules when you code your programs.

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