Sunday, May 26, 2013

HASKELL GHCI DEBUGGER INTRODUCTION

HASKELL GHCI DEBUGGER INTRODUCTION

REVISED: Thursday, February 8, 2024




Haskell GHCi debugger.

I. HASKELL GHCI DEBUGGER

Even though lazy evaluation makes it difficult to apply traditional procedural debugging techniques to Haskell, GHCi contains a simple imperative-style debugger which can stop a running computation in order to examine the values of variables. However, breakpoints and single-stepping are only available in interpreted modules; compiled code is invisible to the debugger.

:sprint can be used to see lazy evaluation by telling you if a variable has been evaluated.

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

Prelude>
let x = 1 + 2 :: Int
Prelude>

Prelude>
:sprint x
x = _  -- Lazy evaluation; therefore, x has not been computed.
Prelude>

Prelude>
x
3 -- A value has been requested for x.
Prelude>

Prelude> :sprint x
x = 3 -- Now Haskell shows a value for x.
Prelude>

A. SAMPLE PROGRAM TO DEBUG

Save the following module as Main.hs to your working directory:

module Main where

import System.IO
import Data.Char(toUpper)

main :: IO ()
main = do 
       inh <- openFile "input.txt" ReadMode
       outh <- openFile "output.txt" WriteMode
       mainloop inh outh
       hClose inh
       hClose outh

mainloop :: Handle -> Handle -> IO ()
mainloop inh outh = 
    do ineof <- hIsEOF inh
       if ineof
           then return ()
           else do inpStr <- hGetLine inh
                        hPutStrLn outh (map toUpper inpStr)
                        mainloop inh outh

Then open GHCi and :load Main.hs as shown below:

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

B. BREAKPOINTS

The GHCi debugger enables dynamic breakpoints and intermediate values observation.

The GHCi debugger provides a way of inspecting code. :b N sets a break point in the loaded module at a specific line. When a breakpoint is set on a particular line, GHCi sets the breakpoint on the leftmost subexpression that begins and ends on that line.

As shown below, breakpoints can be set many different ways. For example, by line; by line and column; by module; by module and line; and by module line and column.

:break line
:break line column
:break module
:break module line
:break module line column

Prelude>  :show breaks
No active breakpoints.
Prelude>

An example of setting a ":break module" breakpoint is shown below:

Prelude>  :break mainloop
Breakpoint 0 activated at Main.hs:(15,1)-(21,35)
Prelude>

As shown above the module mainloop starts on (15,1) line 15 column 1 and ends on (21,36) line 21 column 36.

Prelude>  :show breaks
[0] Main Main.hs:(15,1)-(21,35)
Prelude>

Prelude>  :delete *                      -- To delete all breakpoints at once.
Prelude>

Prelude>  :show breaks
No active breakpoints.
Prelude>    

When stopped at a breakpoint or single-step, GHCi binds the variable _result to the value of the currently active result expression. 

To delete a breakpoint, use the :delete <number> command with the number given in the output from :show breaks.

:list is used to list the source code around the current breakpoint.

:trace  can be used once you have hit a breakpoint, to continue to the next breakpoint, recording the history as you go along.

The following first outputs the message then returns the value of f x.

trace :: String -> a -> a
trace ("calling f with x = " ++ show x) (f x)

The trace function outputs the trace message given as its first argument, before returning the second argument as its result.

:back and :forward allow you to go up and down the list of evaluated expressions and inspect each one.

C. EXAMPLES

As shown below, GHCi uses the flag -fbreak-on-exception to allow you to break into program execution at an arbitrary point.

Prelude>  :set -fbreak-on-exception
Prelude>  

Prelude>  import Debug.Trace
Prelude>

Prelude>  :trace main
Stopped at <exception thrown>
_exception :: e = _
Prelude>

Prelude>  :list
Unable to list source for <exception thrown>
Try :back then :list
Prelude>

Prelude>  :back
Logged breakpoint at Main.hs:19:30-41
_result :: IO String
inh :: Handle
Prelude>

Prelude>  :list
18             then return () 
19             else do inpStr <- hGetLine inh                                  
20                     hPutStrLn outh (map toUpper inpStr) 
Prelude>

Prelude>  :hist
-1  : mainloop (Main.hs:19:30-41)
-2  : mainloop (Main.hs:(17,8)-(21,36))
-3  : mainloop (Main.hs:16:17-26)
-4  : mainloop (Main.hs:(16,5)-(21,36))
-5  : mainloop (Main.hs:(15,1)-(21,36))
-6  : main (Main.hs:10:8-24)
-7  : main (Main.hs:9:16-46)
<end of history>
Prelude>    

II. CONCLUSION

In this tutorial, you have been introduced to the Haskell GHCi debugger.

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.


Thursday, May 23, 2013

HASKELL FIBONACCI SEQUENCE

HASKELL FIBONACCI SEQUENCE

REVISED: Wednesday, January 24, 2024




Haskell Fibonacci sequence.

I. HASKELL FIBONACCI SEQUENCE

The "Fibonacci Sequence" was named after Leonardo "Pisano" Fibonacci an Italian mathematician who was born around 1175 and died around 1250.

The Fibonacci [pronounced fib-on-arch-ee] Sequence is a recursive sequence which obeys the rule that to calculate the next term, one sums the preceding two. For example, the positive index Fibonacci Sequence is the sequence of numbers: 0,1,1,2,3,5,8,13,21,... Each number in the Fibonacci Sequence equals the sum of the two numbers before it. However, there is an exception in regards to the first two numbers in the positive index Fibonacci Sequence. By definition f0 the first number in the positive index Fibonacci Sequence, is 0. Also by definition f1 the second number in the positive index Fibonacci Sequence, is 1. The first two numbers are needed to start the sequence. f2 is computed as 0+1=1. f3 is 1+1=2. f4 is 1+2=3. f5 is 2+3=5, and so on.

f0 = 0 by definition.
f1 = 1 by definition.
f2f0 + f1 = 0 + 1 = 1
f3f1 + f2 = 1 + 1 = 2
f4f2 + f3 = 1 + 2 = 3
f5f3 + f4 = 2 + 3 = 5

The positive index Fibonacci Sequence can also be extended to a negative index; i.e.,
f-n.

EXAMPLE 1

Save the following as fib.hs

fib :: (Eq a, Num a) => a -> a
fib 0 = 0
fib 1 = 1
fib f = fib (f-1) + fib (f-2)

Then open GHCi; :load fib.hs; and run fib as shown below:

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

Prelude>  fib 0    -- fib 0 = 0
0
it :: (Num a, Eq a) => a
Prelude>

Prelude>  fib 1    -- fib 1 = 1
1
it :: (Num a, Eq a) => a
Prelude>

Prelude>  fib 2    -- 0 + 1= 1
1
it :: (Num a, Eq a) => a
Prelude>

Prelude>  fib 3    -- 1 + 1 = 2
2
it :: (Num a, Eq a) => a
Prelude>

Prelude>  fib 4    -- 1 + 2 = 3
3
it :: (Num a, Eq a) => a
Prelude>

Prelude>  fib 5    -- 2 + 3 = 5
5
it :: (Num a, Eq a) => a
Prelude>

Prelude>  fib 6
8
it :: (Num a, Eq a) => a
Prelude>

Prelude>  fib 7
13
it :: (Num a, Eq a) => a
Prelude>

Prelude>  fib 8
21
it :: (Num a, Eq a) => a
Prelude>

Prelude>  fib 9
34
it :: (Num a, Eq a) => a
Prelude>  

EXAMPLE 2

Save the following as fibGen.hs

fib :: (Eq a, Num a, Num a1) => a -> a1
fib f = fibGen 0 1 f

fibGen :: (Eq a, Num a, Num a1) => a1 -> a1 -> a -> a1
fibGen a b f = case f of
0 -> a
f -> fibGen b (a + b) (f - 1)

Then open GHCi; :load fibsGen.hs; and run fib as shown below:

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

Prelude>  fib 0
0
it :: Num a1 => a1
Prelude>

Prelude>  fib 1
1
it :: Num a1 => a1
Prelude>

Prelude>  fib 2
1
it :: Num a1 => a1
Prelude>

Prelude>  fib 3
2
it :: Num a1 => a1
Prelude>

Prelude>  fib 4
3
it :: Num a1 => a1
Prelude>

Prelude>  fib 5
5
it :: Num a1 => a1
Prelude>

Prelude>  fib 6
8
it :: Num a1 => a1
Prelude>

Prelude>  fib 7
13
it :: Num a1 => a1
Prelude>

Prelude>  fib 8
21
it :: Num a1 => a1
Prelude>

Prelude>  fib 9
34
it :: Num a1 => a1
Prelude> 

EXAMPLE 3

Save the following as fibs.hs

fibs :: [Integer]
fibs = 0 : 1 : [ a + b | (a, b) <- zip fibs (tail fibs)]

Then open GHCi; :load fibs.hs; and run fibs as shown below:

Prelude>  fibs !! 0
0
it :: Integer
Prelude>

Prelude>  fibs !! 1
1
it :: Integer
Prelude>

Prelude>  fibs !! 2
1
it :: Integer
Prelude>

Prelude>  fibs !! 3
2
it :: Integer
Prelude>

Prelude>  fibs !! 4
3
it :: Integer
Prelude>

Prelude>  fibs !! 5
5
it :: Integer
Prelude>

Prelude>  fibs !! 6
8
it :: Integer
Prelude>

Prelude>  fibs !! 7
13
it :: Integer
Prelude>

Prelude>  fibs !! 8
21
it :: Integer
Prelude>

Prelude>  fibs !! 9
34
it :: Integer
Prelude>

!! is the index operator for lists in Haskell. Haskell lists are 0-indexed.

Prelude>  [0,1,1,2,3,5,8,13,21,34]!!0
0
it :: Num a => a
Prelude>

Prelude>  [0,1,1,2,3,5,8,13,21,34]!!1
1
it :: Num a => a
Prelude>

Prelude>  [0,1,1,2,3,5,8,13,21,34]!!2
1
it :: Num a => a
Prelude>

Prelude>  [0,1,1,2,3,5,8,13,21,34]!!3
2
it :: Num a => a
Prelude>

Prelude>  [0,1,1,2,3,5,8,13,21,34]!!4
3
it :: Num a => a
Prelude>

Prelude>  [0,1,1,2,3,5,8,13,21,34]!!5
5
it :: Num a => a
Prelude>

Prelude>  [0,1,1,2,3,5,8,13,21,34]!!6
8
it :: Num a => a
Prelude>

Prelude>  [0,1,1,2,3,5,8,13,21,34]!!7
13
it :: Num a => a
Prelude>

Prelude>  [0,1,1,2,3,5,8,13,21,34]!!8
21
it :: Num a => a
Prelude>

Prelude>  [0,1,1,2,3,5,8,13,21,34]!!9
34
it :: Num a => a
Prelude>  

Using tail recursion, while slightly more complex, will prevent the exponential growth of function calls.

The value of tail recursion is that in a tail recursive call, the "caller" does nothing except pass up the value that is returned by the "callee"; and that, in turn, means that you do not need to return to the "caller". If you think of it in terms of primitive machine-level code, in a tail recursive call, you can use a direct branch instruction instead of a branch to subroutine; the tail recursive call does not need to create a new stack frame. It can just reuse the "callers" frame.

Prelude>  tail [0,1,1,2,3,5,8,13,21,34]
[1,1,2,3,5,8,13,21,34]
it :: Num a => [a]
Prelude>

Prelude>  zip [0,1,1,2,3,5,8,13,21,34] $ tail [0,1,1,2,3,5,8,13,21,34]
[(0,1),(1,1),(1,2),(2,3),(3,5),(5,8),(8,13),(13,21),(21,34)]  -- (a, b) <-
it :: (Num b, Num a) => [(a, b)]
Prelude>  

Prelude>  let y = 0 : 1 : [ a + b | (a,b) <- zip [0,1,1,2,3,5,8,13,21,34] $ tail [0,1,1,2,3,5,8,13,21,34]]
y :: Num a => [a]
Prelude>

Prelude>  y
[0,1,1,2,3,5,8,13,21,34,55]    -- The Fibonacci Sequence...
it :: Num a => [a]
Prelude>  

EXAMPLE 4

Prelude> import Data.List

Prelude Data.List> fibs = 0 : scanl (+) 1 fibs


Prelude Data.List>
take 10 fibs
[0,1,1,2,3,5,8,13,21,34]   -- The Fibonacci Sequence...


Prelude Data.List>


EXAMPLE 5

Save the following as fibs5.hs


import System.Environment (getArgs)

main = do
     args <- getArgs
     let n = (read (args !! 0) :: Int)
     putStrLn (show (fibs !! (n-1)))

fibs = 0 : 1 : [ a + b | (a, b) <- zip fibs (tail fibs) ]

Then open GHCi; :load fibs5.hs; and run fibs as shown below:

*Main>  take 10 fibs
[0,1,1,2,3,5,8,13,21,34]
*Main>


II. 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 been introduced to the Haskell Fibonacci sequence.


Tuesday, May 21, 2013

HASKELL FUNCTION COMPOSITION

HASKELL FUNCTION COMPOSITION

REVISED: Friday, February 9, 2024




Haskell function composition.

I. HASKELL FUNCTION COMPOSITION

There are two main operations we can do with function values: apply them, and compose them. Haskell's laziness gives us compositionality.

The nesting of two or more functions to form a single new function is known as composition.

f (g x) = (f . g) x

Read as f of g is the composition of f with g.

The composition of f and g is a function that first applies g to its argument, then f to the value returned by g. It then returns the return value of f.

The primary purpose of the Haskell function composition . dot operator is to chain functions of the same type. It lets us tie the output of whatever appears on the right of the dot operator to the input of whatever appears on the left of the dot operator as long as they are of the same type.

The programming style of function composition, is called "pointfree" style, which means the arguments to the function are omitted. In many cases this makes for clearer code. Function composition is a common Haskell idiom. It is very common for functional programmers to write functions as a composition of other functions of the same type, never mentioning the actual arguments they will be applied to.

Pointfree style is often referred to as "pointless" style.

Composition is associative; for example, when more than two numbers are added or multiplied, the result remains the same, irrespective of how they are grouped.

EXAMPLE 1

λx.(3 + 4 * x) `div` 3
=
\x -> (3 + 4 * x) `div` 3

Prelude>  let y x = (3 + 4 * x) `div` 3
y :: Integral a => a -> a
Prelude>

Prelude>  y 3
5
it :: Integral a => a
Prelude>

Prelude>  let y x = (`div` 3) (3 + 4 * x)
y :: Integral a => a -> a
Prelude>

Prelude>  y 3
5
it :: Integral a => a
Prelude>  

Prelude> let y = (`div` 3) . (+ 3) . (* 4)
y :: Integral c => c -> c
Prelude>

Prelude>  y 3
5
it :: Integral c => c
Prelude>  

Step 1:
(* 4) -- Means 3 * 4
12

Step 2:
(+ 3) . (* 4)  -- Means 12 + 3
15

Step 3:
(`div` 3)  -- Means 15 `div` 3
5

EXAMPLE 2


Prelude>  let y = take 3 (reverse (filter even [1..10]))  -- Using ( ) instead of $
y :: Integral a => [a]
Prelude>

Prelude>  y
[10,8,6]
it :: Integral a => [a]
Prelude>  

Prelude>  let y = take 3 . reverse . filter even [1..10]  -- With no $ [1..10] 

<interactive>:33:28:
    Couldn't match expected type ‘a -> [a1]’ with actual type ‘[a0]’
    Relevant bindings include
      y :: a -> [a1] (bound at <interactive>:33:5)
    Possible cause: ‘filter’ is applied to too many arguments
    In the second argument of ‘(.)’, namely ‘filter even [1 .. 10]’
    In the second argument of ‘(.)’, namely
      ‘reverse . filter even [1 .. 10]’
Prelude>  

The dot operator expects its second argument to be a function of one argument, not a list.

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

Prelude>  :info (.)
(.) :: (b -> c) -> (a -> b) -> a -> c -- Defined in `GHC.Base'
infixr 9 .  -- Priority of 9.
Prelude>   

Function application has priority of 10, while function composition has a lower priority of 9. Therefore, we need the $ operator to allow function composition to evaluate first.

Prelude>  let y = take 3 . reverse . filter even $ [1..10]
y :: Integral a => [a]
Prelude>

Prelude>  y
[10,8,6]
it :: Integral a => [a]
Prelude> 

Step 1:
Prelude> filter even $ [1..10]
[2,4,6,8,10]
Prelude>

Step 2:
Prelude> reverse [2,4,6,8,10]
[10,8,6,4,2]
Prelude>

Step 3:
Prelude> take 3 [10,8,6,4,2]
[10,8,6]
Prelude>

II. CONCLUSION

In this tutorial, you have seen examples of  the associative nature of Haskell function composition.

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, May 19, 2013

HASKELL BINDING AND SCOPE INTRODUCTION

HASKELL BINDING AND SCOPE INTRODUCTION

REVISED: Saturday, February 10, 2024




Haskell binding and scope.

Local bindings are values inside of a function that only that function can see.

I. HASKELL BINDING AND SCOPE

A. HASKELL BINDING AND SCOPE EXAMPLES

1. Variables in a Haskell where clause

The function fA1, shown below, is defined at the top level; and its scope is the program, it can be used anywhere in the program.

The scope of the functions y and z, shown below, is the function fA1; they have no value outside of the function fA1

The scope of the variable x is the function fA1 which includes the where clause; x has no value outside of the function fA1.  The variable x only has meaning while the function fA1 is being applied to the variable x.

fA1 :: Num a => a -> a
fA1 x = z
      where
      y = x + 1
      z = x + y * y

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

Prelude>  fA1 2
11
it :: Num a => a
Prelude>

Steps:
fA1 2
y = x + 1 therefore 
y  = 2  + 1 = 3
z = x + y * y therefore
z = 2 + 3 * 3 = 11

2. Functions in a Haskell where clause

The function fA2 is defined at the top level; and its scope is the program, it can be used anywhere in the program.

The scope of the function g is the function fA2; g has no value outside of the function fA2.

The scope of the variable x is the function fA2 which includes the where clause; x has no value outside of the function fA2

The scope of the variable y is the function g; y has no value outside of the function g.

fA2 :: Num a => a -> a
fA2 x = g (x+1)   -- Actual implied y is (x + 1).
      where
      g y = x+y*y   -- Formal y is bound to actual (x + 1).

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

Prelude>  fA2 2
11
it :: Num a => a
Prelude>  

Steps:
fA2 2
fA2 x = g (x+1) therefore
fA2 2 = g (2+1) = g (3)   -- Actual implied y
g y = x+y*y
g 3 = 2 + 3 * 3 = 11

3. Haskell lambda functions

Below are two lambda functions, their x variables do not share scope. An x variable in one lambda function is not the same x variable in the other lambda function.

Binding occurrence of function x.

Binding occurrence of function x.

fA3 :: [Int] -> [Int]
fA3 xs = map (\x -> x*x) (filter (\x -> x >0) xs)

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

Prelude>  fA3 [1,2,-3]
[1,4]
it :: [Int]
Prelude>  



II. CONCLUSION

In this tutorial, you have been introduced to Haskell binding and scope.

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.