Thursday, June 1, 2023

HASKELL IS A TOOL

HASKELL MONAD OVERVIEW

REVISED: Monday, October 7, 2024


1. INTRODUCTION

Haskell is a powerful programming language that is well-suited for a variety of tasks.

2. OVERVIEW

For example Haskell is well-suited for tasks including:

Functional programming: Haskell is a purely functional language, which means that it does not have side effects. This makes it ideal for tasks that require a high degree of mathematical precision, such as symbolic computation and artificial intelligence.

Concurrent programming: Haskell has built-in support for concurrent programming, which makes it ideal for tasks that require multiple threads of execution, such as web servers and distributed systems.

Data analysis: Haskell has a rich set of libraries for data analysis, making it ideal for tasks such as data mining and machine learning.

However, Haskell is not without its drawbacks. It can be difficult to learn, and it is not as widely used as other programming languages, such as Java and Python. This can make it difficult to find help and resources when you are using Haskell.

Here are some tasks that are better suited for other programming languages:

Web development: Haskell is not a good choice for web development. There are few web frameworks available for Haskell, and the language's performance can be a bottleneck for high-traffic websites.

Graphics programming: Haskell is not a good choice for graphics programming. The language does not have built-in support for graphics libraries, and its performance can be a bottleneck for graphics-intensive applications.

Game development: Haskell is not a good choice for game development. The language does not have built-in support for game engines, and its performance can be a bottleneck for games with complex graphics and physics.

3. CONCLUSION

Overall, Haskell is a powerful programming language that is well-suited for a variety of tasks. However, it is important to choose the right tool for the job. If you are working on a task that requires a high degree of mathematical precision, concurrent programming, or data analysis, then Haskell is a good choice. However, if you are working on a task that is better suited for a different programming language, then you should choose that language instead.

4. 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, May 30, 2023

HASKELL MONAD OVERVIEW

HASKELL MONAD OVERVIEW

REVISED: Sunday, October 13, 2024


1. INTRODUCTION

What is a monad?

A monad is a type constructor we will refer to as M, with two operations we will refer to as return and bind.

The operation return takes a value of type a and returns a value of type M a.

The operation bind takes a value of type M a and a function of type a -> M b, and returns a value of type M b.

The return operation is used to create new monadic values, and the bind operation is used to chain together monadic computations.

2. OVERVIEW

Why use monads?

Monads are a powerful tool for structuring computations. They can represent various computational concepts, such as state, sequencing, and exceptions.

State: Monads can be used to represent computations that have side effects, such as reading or writing to a file.

Sequencing: Monads can be used to represent computations that need to be executed in a specific order.

Exceptions: Monads can be used to represent computations that can fail.

Haskell has many built-in monads, including:

Maybe: This monad represents computations that can fail.

IO: This monad represents computations that have side effects.

State: This monad represents computations that have mutable states.

3. EXAMPLE

Here is an example of how to use the Maybe monad to represent a computation that can fail:

-- mayMon.hs

import Control.Monad()

{-
The function divide x y returns a Maybe Integer, representing the result of dividing two numbers. x is the numerator, y is the denominator. 
-}

divide :: Integer -> Integer -> Maybe Integer
divide x y =
  if y == 0 then Nothing else Just (x `div` y)

{-
The function main uses the `Maybe` monad to print the result of dividing x by y.
-}

main :: IO ()
main = do
  xStr <- readLn
  yStr <- readLn
  result <- divide x y
  case result of
    Just z -> print z
    Nothing -> putStrLn "Division by zero!"

This program effectively handles division by zero using the Maybe monad, providing a Nothing value in such cases and printing an appropriate error message.

Here's a breakdown of the code:

  • import Control.Monad(): Imports the Control.Monad module, which provides essential functions and type classes for working with monads, including Maybe.
  • divide :: Integer -> Integer -> Maybe Integer: Defines a function named divide that takes two Integer arguments (numerator and denominator) and returns a Maybe Integer quotient result.
  • if y == 0 then Nothing else Just (xdivy): Uses a conditional expression to check if the denominator (y) is zero. If it is, the function returns Nothing to indicate an error (division by zero). Otherwise, it returns Just (xdivy), where xdivy performs integer division and Just wraps the result in a Maybe value.
  • main :: IO (): Defines the main function that executes the program's logic.
  • x <- readLn: Reads an Integer value from the standard input and binds it to the variable x.
  • y <- readLn: Reads another Integer value from the standard input and binds it to the variable y.
  • result <- divide x y: Calls the divide function with the values of x and y, binds the result (either Just z or Nothing) to the variable result.
  • case result of: Uses a pattern matching case expression to handle the different possible values of result.
  • Just z -> print z: If result is Just z, it prints the value of z (the result of the division).
  • Nothing -> putStrLn "Division by zero!": If result is Nothing, it prints the error message "Division by zero!".

This program effectively demonstrates the use of the Maybe monad for handling potential errors and providing meaningful feedback to the user.

4. CONCLUSION

Monads are a powerful tool for structuring computations in Haskell. They can be used to represent a wide variety of computational concepts, such as state, sequencing, and exceptions.

This tutorial has helped you to learn how to program using Haskell monads.

5. 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, May 20, 2023

HASKELL APPLICATIVE STYLE

HASKELL APPLICATIVE STYLE

REVISED: Monday, September 23, 2024


1. INTRODUCTION

You are probably familiar with imperative style programming. This tutorial introduces applicative style programming.

In this tutorial, we'll take a look at applicative functors, which are beefed up functors, represented in Haskell by the Applicative typeclass, found in the Control.Applicative module.

The definition of Functor is:

class Functor f where
    fmap :: (a -> b) -> fa -> fb

GHCi, version 9.8.1: https://www.haskell.org/ghc/  :? for help
ghci> fmap (+1) (Just 1)
Just 2
ghci>

The definition of Applicative is:

class (Functor f) => Applicative f where  
    pure :: a -> f a  
    (<*>) :: f (a -> b) -> f a -> f b  

If we want to make a type constructor part of the Applicative typeclass, it has to be in Functor first. That's why if we know that a type constructor is part of the Applicative typeclass, it's also in Functor, so if we want to we can use fmap on it.

The first method defined above is called pure. Its type declaration is pure :: a -> f a. f plays the role of an applicative functor instance. pure takes a value of any type and returns an applicative functor with that value inside it.

The <*> function has a type declaration of  (<*>) :: f (a -> b) -> f a -> f b. Which should remind you of fmap :: (a -> b) -> f a -> f b.  <*> is a sort of beefed up fmap. However, where fmap takes a function and a functor and applies the function inside the functor, <*> takes a functor that has a function in it and another functor and extracts that function from the first functor and then maps it over the second one.

Haskell Applicative style <*> is left-associative; and <*> is read as "applied to".

2. OVERVIEW

Imperative style tells the computer what to do step-by-step.

Applicative style tells the computer what you want the final result to be, and the computer figures out how to get there. The Applicative type class provides a way to combine functions that take multiple arguments into a single function that takes a single argument. To use the Applicative type class, we first need to create an instance of the type class for our function. An instance of a type class is a definition that tells the compiler how to use the type class with our function. Once we have an instance of the Applicative type class, we can write a function; for example, an addTwoNumbers function in applicative style. The addTwoNumbers function in applicative style would be much more concise and easier to read than the imperative version of the function. It will also be more efficient, because the computer doesn't have to figure out how to get the final result step-by-step.

3. HASKELL EXAMPLES

Following are two Haskell programs.

The first program is written in Imperative Style Haskell.

The second program rewrites the first program into Applicative Style Haskell.

-- First Program:  Imperative Style Haskell Programming

addTwoNumbers :: Int -> Int -> Int
addTwoNumbers x y = x + y

main :: IO ()
main = do
    a <- readLn
    b <- readLn
    print $ addTwoNumbers a b

GHCi, version 9.8.1: https://www.haskell.org/ghc/  :? for help
Prelude> :cd c:\users\tinnel\haskell2024\
Prelude> :l imperative.hs
[1 of 1] Compiling Main             ( imperative.hs, interpreted )
Ok, one module loaded.
*Main> main
1
2
3
*Main>

-- Second Program:  Applicative Style Haskell Computer Programming

import Control.Applicative ()

addTwoNumbers :: Int -> Int -> Maybe Int
addTwoNumbers x y = Just $ x + y

main :: IO ()
main = do
    a <- readLn
    b <- readLn
    print $ addTwoNumbers a b

GHCi, version 9.8.1: https://www.haskell.org/ghc/  :? for help
ghci> :cd c:\users\tinnel\haskell2024\
ghci> :l applicative.hs
[1 of 2] Compiling Main             ( applicative.hs, interpreted )
Ok, one module loaded.
ghci> main
1
2
Just 3
ghci>

The first program is written in imperative style, which means that it tells the computer what to do step-by-step.

The second program is written in applicative style, which means that it tells the computer what to do with the values, rather than how to do it.

The first program works by first reading two numbers from the user, then adding them together, and finally printing the sum.

The second program works by first creating two applicative functors, one for each number, then applying the addTwoNumbers function to the two applicative functors, and finally printing the result.

The main difference between the two programs is that the second program does not specify how the numbers are added together. Instead, it specifies that the numbers should be added together, and leaves it up to the compiler to figure out how to do it. This makes the second program more efficient, because the compiler can optimize the code to use the most efficient method of adding the numbers together.

Maybe is a form of applicative programming. Applicative programming is a style of programming that uses applicative functors to represent computations. Applicative functors are like monads but they do not have side effects. This makes them more efficient, because the compiler can optimize the code to avoid running computations that are not needed.

In the Maybe example, the addTwoNumbers function is an applicative functor. It takes two values as input and returns a value. The Just constructor is used to create an applicative functor with a value, and the Nothing constructor is used to create an applicative functor that is empty.

In this example, we use the readLn function to read two numbers from the user. We then use the addTwoNumbers function to add them. If the addition is successful, the addTwoNumbers function will return a Just containing the result. If the addition is not successful, the addTwoNumbers function will return Nothing.

Finally, we use the print function to print the result of the addition. If the addition was successful, the print function will print the result. If the addition was not successful, the print function will not print anything.

Applicative style is a way of writing Haskell code that makes use of the Applicative type class. The Applicative type class provides a way to combine functions that return values of different types. This can be useful for a variety of tasks, such as composing functions, creating pipelines, and working with data that is represented as a tree.

4. CONCLUSION

In order to use Applicative style, we first need to create an instance of the Applicative type class for our function. This can be done by providing implementations of the following methods:

pure: This method takes a value of any type and returns an Applicative instance that wraps the value.

(<*>): This method takes two Applicative instances and returns an Applicative instance that represents the composition of the two functions.

Once we have created an instance of the Applicative type class for our function, we can use it to write code in Applicative style.

5. 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, February 28, 2019

HASKELL COMMAND LINE ARGUMENTS

HASKELL COMMAND LINE ARGUMENTS

REVISED: Wednesday, January 24, 2024


1. INTRODUCTION

Haskell code can be run interactively using GHCi or compiled to an executable using GHC. A command-line is a line of code used to compile a Haskell program using the GHC compiler.

2. OVERVIEW

In Haskell, you can access the command-line arguments with the function getArgs. Import System.Environment to get access to the getArgs function. The getArgs function is not interactive. It will just return the arguments supplied from the command-line, if any were supplied. If you do not supply any arguments at the command-line, then the returned list will be empty as shown in Example 1 below.

Command-line arguments used in GHC are either options or file names. Command-line options begin with -. Command-line options are order-dependent, with arguments being evaluated from left-to-right.

3. EXAMPLE 1

GHCi, version 9.8.1: http://www.haskell.org/ghc/  :? for help
Prelude> :m + System.Environment
Prelude System.Environment> :t getArgs
getArgs :: IO [String]
Prelude System.Environment> do a <- getArgs; print a
[]     -- Empty, because we did not provide any arguments.
Prelude System.Environment> 

4. EXAMPLE 2

This is an example of a program loaded into GHCi and run interactively.

-- Program Name: Interactive.hs

add x y = x + y

total [] = 0
total [x] = x
total (x:xs) = add x (total xs)

compute xs = show $ total $ map read xs

main = do
    putStrLn "Enter first number."
    num1 <- getLine
    putStrLn "Enter second number."
    num2 <- getLine
    putStrLn "Enter last number."
    num3 <- getLine
    putStrLn $ "Total is: " ++ compute [num1, num2, num3]

Prelude> :l Interactive.hs
[1 of 1] Compiling Main             ( Interactive.hs, interpreted )
Ok, one module loaded.
*Main> main
Enter first number.
3
Enter second number.
5
Enter last number.
7
Total is: 15
*Main> 


5. CONCLUSION

A programmer can automate the execution of a program by using command-line arguments in GHC when they compile their Haskell program.


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

Friday, January 27, 2017

HASKELL PROOF BY MATHEMATICAL INDUCTION EXAMPLE 1

HASKELL PROOF BY MATHEMATICAL INDUCTION EXAMPLE 1

REVISED: Saturday, October 5, 2024


1. INTRODUCTION

This tutorial introduces using Haskell for proof by Mathematical Induction that an infinite equation's left-hand side (LHS) equals the right-hand side (RHS).

Recursive proofs are called induction. Mathematical Induction is a method of formal proof in which a statement is proved for one step in a process, and it is shown that if the statement holds for that step, it holds for the next. The beauty of induction is that it allows a theorem to be proven true where an infinite number of cases exist without exploring each case individually.

Step 1. Show that the statement is true for the initial lowest value of n, which is often n = 1.

Step 2. Assume that the statement is true for n = k.

Step 3. Use the assumption in "Step 2." to prove that the statement is true for n = k + 1.

Then it follows the statement must be true for all values of n.

2. GHCi RUN

GHCi, version 9.8.1: http://www.haskell.org/ghc/  :? for help
Prelude> :l mathematicalInduction
[1 of 1] Compiling Main             ( mathematicalInduction.hs, interpreted )
Ok, modules loaded: Main.
*Main> main

==========================================================

Prove: 2 + 4 + 6 +...+ (2*n) = n*(n+1) by mathematical induction.

Step 1: Show it is True for n = 1.

LHS = 2*n and RHS = n*(n+1).

LHS = 2 and RHS = 2.

LHS = RHS; therefore, it is True for n = 1.

==========================================================

Prove: 2 + 4 + 6 +...+ (2*n) = n*(n+1) by mathematical induction.

Step 2: Assume it is True for n = k.

That is: 2 + 4 + 6 +...+ (2*k) = k*(k+1).

==========================================================

Prove: 2 + 4 + 6 +...+ (2*n) = n*(n+1) by mathematical induction.

Step 3: Show it is True for n = k + 1.

That is: 2 + 4 + 6 +...+ (2 * k) + 2 * (k + 1) = (k + 1) * (k + 2).

LHS = 2 + 4 + 6 + ... + (2 * k) + 2 * (k + 1)
= k * (k + 1) + 2 * (k + 1)
= (k + 1) * ( (k * 1) + (2 * 1))
= (k + 1) * (k + 2) = RHS

Therefore, it is True for n = k + 1.

Therefore, the statement is True for n >= 1.

Q.E.D.

==========================================================

*Main>

3. HASKELL PROGRAM

The Haskell program is as follows:

-- C:\Users\Tinnel\Haskell2024\mathematicalInduction.hs

{-

LHS is the left-hand side of the = sign.
RHS is the right-hand side of the = sign.

Prove 2+4+6+...+(2*n) = n * (n+1) by mathematical induction.

Step 1. Show that the statement is true for the initial value of n = 1.

LHS = 2 * 1 = 2
RHS = 1 * (1 + 1) = 2

LHS == RHS

-}

import System.IO
import Data.List

l :: Num t => t
l = 1

r :: Num t => t
r = 1

lHs :: Num a => a -> a
lHs l = 2 * l

rHs :: Num a => a -> a
rHs r = r * (r + 1)

main :: IO ()
main = do {  putStrLn ""  -- putStrLn Has type I/O action.
           ; putStrLn "=========================================================="
           ; putStrLn ""
           ; putStrLn "Prove: 2 + 4 + 6 +...+ (2*n) = n*(n+1) by mathematical induction."
           ; putStrLn ""
           ; putStrLn "Step 1: Show it is True for n = 1."
           ; putStrLn ""
           ; putStrLn ("LHS = 2*n and " ++ "RHS = n*(n+1).")
           ; putStrLn ""
           ; let lS = show (lHs l)  -- Type converted from Integer z to String z.
           ; let rS = show (rHs r)  -- Type converted from Integer z to String z.
           ; putStrLn ("LHS = " ++ lS ++ " and RHS = " ++ rS ++ ".")
           ; putStrLn ""
           ; let i = if (lHs l == rHs r) then "True" else "False"
           ; putStrLn ("LHS = RHS; therefore, it is " ++ i ++ " for n = 1.")
           ; putStrLn ""
           ; putStrLn "=========================================================="
           ; putStrLn ""
           ; putStrLn "Prove: 2 + 4 + 6 +...+ (2*n) = n*(n+1) by mathematical induction."
           ; putStrLn ""
           ; putStrLn "Step 2: Assume it is True for n = k."
           ; putStrLn ""
           ; putStrLn "That is: 2 + 4 + 6 +...+ (2*k) = k*(k+1)."
           ; putStrLn ""
           ; putStrLn "=========================================================="
           ; putStrLn ""
           ; putStrLn "Prove: 2 + 4 + 6 +...+ (2*n) = n*(n+1) by mathematical induction."
           ; putStrLn ""
           ; putStrLn "Step 3: Show it is True for n = k + 1."
           ; putStrLn ""
           ; putStrLn "That is: 2 + 4 + 6 +...+ (2 * k) + 2 * (k + 1) = (k + 1) * (k + 2)."
           ; putStrLn ""
           ; putStrLn "LHS = 2 + 4 + 6 + ... + (2 * k) + 2 * (k + 1)"
           ; putStrLn ""
           ; putStrLn "= k * (k + 1) + 2 * (k + 1)"
           ; putStrLn ""
           ; putStrLn "= (k + 1) * ( (k * 1) + (2 * 1))"
           ; putStrLn ""
           ; putStrLn "= (k + 1) * (k + 2) = RHS"
           ; putStrLn ""
           ; putStrLn "Therefore, it is True for n = k + 1."
           ; putStrLn ""
           ; putStrLn "Therefore, the statement is True for n >= 1."
           ; putStrLn ""
           ; putStrLn "Q.E.D."
           ; putStrLn ""
           ; putStrLn "=========================================================="
           ; putStrLn ""
          }
--

4. CONCLUSION

Using Haskell and Mathematical Induction we have proven 2+4+6+...+(2*n) = n * (n+1).

5. 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, January 19, 2017

HASKELL AND YOUR AGE BY CHOCOLATE

HASKELL AND YOUR AGE BY CHOCOLATE

REVISED: Saturday, October 5, 2024


1. INTRODUCTION

This tutorial is for having fun with Haskell.

2. HASKELL PROGRAM

The Haskell program is as follows:

-- C:\Users\Tinnel\Haskell2024\age.hs

import Data.List
import System.IO

main :: IO ()  -- Has type I/O action.
main = do {  putStrLn ""  -- putStrLn Has type I/O action.
           ; putStrLn "=========================================================="
           ; putStrLn ""
           ; putStrLn "CALCULATING YOUR AGE BY CHOCOLATE!"
           ; putStrLn ""
           ; putStrLn "First, type a positive integer from 1 to 10 indicating how"
           ; putStrLn "often you crave chocolate each week, then press Enter."
           ; cewS <- getLine -- getLine is a function, getLine :: IO String
           ; putStrLn ""
           ; let runTot1I = (read cewS)::Integer
           ; let runTot1S = show runTot1I
           ; putStrLn ("Running Total: " ++ runTot1S)
           ; putStrLn ""
           ; putStrLn "=========================================================="
           ; putStrLn ""
           ; let cewI = (read cewS)::Integer
           ; let cewIx2I = cewI * 2
           ; let cewIx2S = show cewIx2I
           ; putStrLn ("Second, we multiply " ++ cewS ++ " by 2 which equals " ++ cewIx2S ++ ".")
           ; putStrLn ""
           ; let runTot2I = runTot1I * 2
           ; let runTot2S = show runTot2I
           ; putStrLn ("Running Total: " ++ runTot2S)
           ; putStrLn ""
           ; putStrLn "=========================================================="
           ; putStrLn ""
           ; let cewIp5I = cewIx2I + 5
           ; let cewIp5S = show cewIp5I
           ; putStrLn ("Third, we add 5 to our running total which equals " ++ cewIp5S ++ ".")
           ; putStrLn ""
           ; let runTot3I = runTot2I + 5
           ; let runTot3S = show runTot3I
           ; putStrLn ("Running Total: " ++ runTot3S)
           ; putStrLn ""
           ; putStrLn "=========================================================="
           ; putStrLn ""
           ; let cewIp5x50I = cewIp5I * 50
           ; let cewIp5x50S = show cewIp5x50I
           ; putStrLn ("Fourth, we multiply our running total by 50 which equals " ++ cewIp5x50S ++ ".")
           ; putStrLn ""
           ; let runTot4I = runTot3I * 50
           ; let runTot4S = show runTot4I
           ; putStrLn ("Running Total: " ++ runTot4S)
           ; putStrLn ""
           ; putStrLn "=========================================================="
           ; putStrLn ""
           ; putStrLn "Fifth, type the current year date as a positive integer; e.g., 2017"
           ; putStrLn "then press Enter."
           ; yearS <- getLine -- getLine is a function, getLine :: IO String
           ; putStrLn ""
           ; putStrLn ("Running Total: " ++ runTot4S)
           ; putStrLn ""
           ; putStrLn "=========================================================="
           ; putStrLn ""
           ; let yearI = (read yearS)::Integer
           ; let runTotI = cewIp5x50I + (yearI - 250)
           ; let runTotS = show runTotI
           ; putStrLn "Sixth, we subtract 250 from the current year; e.g., 2017 - 250 = 1767"
           ; putStrLn ("and add the result to our running total which equals " ++ runTotS ++ ".")
           ; putStrLn ""
           ; let runTot6I = runTot4I + (yearI - 250)
           ; let runTot6S = show runTot6I
           ; putStrLn ("Running Total: " ++ runTot6S)
           ; putStrLn ""
           ; putStrLn "=========================================================="
           ; putStrLn ""
           ; putStrLn "Seventh, if you have not had your birthday this year type the integer 1."
           ; putStrLn "If you have had your birthday this year type zero; e.g., 0."
           ; putStrLn "Then press Enter."
           ; birthdayS <- getLine -- getLine is a function, getLine :: IO String
           ; putStrLn ""
           ; putStrLn ("Running Total: " ++ runTot6S)
           ; putStrLn ""
           ; putStrLn "=========================================================="
           ; putStrLn ""
           ; let birthdayI = (read birthdayS)::Integer
           ; let runTotMI = (runTotI - birthdayI)
           ; let runTotMS = show runTotMI
           ; putStrLn "Eighth, we subtract 1 or 0 from the running total."
           ; putStrLn ""
           ; putStrLn ("Now our running total equals " ++ runTotMS ++ ".")
           ; putStrLn ""
           ; let runTot8I = (runTot6I - birthdayI)
           ; let runTot8S = show runTot8I
           ; putStrLn ("Running Total: " ++ runTot8S)
           ; putStrLn ""
           ; putStrLn "=========================================================="
           ; putStrLn ""
           ; putStrLn "Ninth, type the year of your birth; e.g., 1992"
           ; putStrLn "then press Enter."
           ; birthYearS <- getLine -- getLine is a function, getLine :: IO String
           ; putStrLn ""
           ; putStrLn ("Running Total: " ++ runTot8S)
           ; putStrLn ""
           ; putStrLn "=========================================================="
           ; putStrLn ""
           ; let birthYearI = (read birthYearS)::Integer
           ; let runTotBYI = (runTotMI - birthYearI)
           ; let runTotBYS = show runTotBYI
           ; putStrLn "Tenth, we subtract the year you were born from the running total."
           ; putStrLn ""
           ; putStrLn ("Now our running total equals " ++ runTotBYS ++ ".")
           ; putStrLn ""
           ; let runTot10I = (runTot8I - birthYearI)
           ; let runTot10S = show runTot10I
           ; putStrLn ("Running Total: " ++ runTot10S)
           ; putStrLn ""
           ; putStrLn "=========================================================="
           ; putStrLn ""
           ; putStrLn "The running total's first two digits are how often you crave chocolate each week."
           ; putStrLn ""
           ; putStrLn "The last two digits of the running total are your Age By Chocolate."
           ; putStrLn ""
           ; putStrLn ("Running Total: " ++ runTot10S)
           ; putStrLn ""
           ; putStrLn "=========================================================="
           ; putStrLn ""
          }
--

3. GHCi RUN

GHCi, version 9.8.1: http://www.haskell.org/ghc/  :? for help
Prelude> :l age
[1 of 1] Compiling Main             ( age.hs, interpreted )
Ok, modules loaded: Main.

*Main> main
==========================================================

CALCULATING YOUR AGE BY CHOCOLATE!

First, type a positive integer from 1 to 10 indicating how
often you crave chocolate each week, then press Enter.
10

Running Total: 10

==========================================================

Second, we multiply 10 by 2 which equals 20.

Running Total: 20

==========================================================

Third, we add 5 to our running total which equals 25.

Running Total: 25

==========================================================

Fourth, we multiply our running total by 50 which equals 1250.

Running Total: 1250

==========================================================

Fifth, type the current year date as a positive integer; e.g., 2017
then press Enter.
2017

Running Total: 1250

==========================================================

Sixth, we subtract 250 from the current year; e.g., 2017 - 250 = 1767
and add the result to our running total which equals 3017.

Running Total: 3017

==========================================================

Seventh, if you have not had your birthday this year type the integer 1.
If you have had your birthday this year type zero; e.g., 0.
Then press Enter.
0

Running Total: 3017

==========================================================

Eighth, we subtract 1 or 0 from the running total.
Now our running total equals 3017.

Running Total: 3017

==========================================================

Ninth, type the year of your birth; e.g., 1992
then press Enter.
1992

Running Total: 3017

==========================================================

Tenth, we subtract the year you were born from the running total.
Now our running total equals 1025.

Running Total: 1025

==========================================================

The first two digits of the running total are how often you crave chocolate each week.
The last two digits of the running total are your Age By Chocolate.

Running Total: 1025

==========================================================
*Main>

4. CONCLUSION

You can have fun with Haskell.

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



Friday, January 13, 2017

HASKELL PUBLIC KEY CRYPTOGRAPHY USING PRIME NUMBERS

HASKELL PUBLIC KEY CRYPTOGRAPHY USING PRIME NUMBERS

REVISED: Monday, September 23, 2024


1. INTRODUCTION

Prime numbers are significant for Internet security.

For example, a Bank could start with two large prime numbers p1 and p2. The Bank computer multiplies p1 * p2 and the result is used to create a Public Key to encrypt a Customer credit card.

The Bank keeps p1 and p2 secret. Therefore, p1 and p2 are referred to as Secret Keys.

The Secret Keys must be kept secret because they will be used to decrypt the credit card transactions received by the Bank. Once successfully decrypted the credit card transaction will access the Customer's credit card bank balance and increase or decrease the Customer's credit card account.

Prime Factorization using a tree is one decryption method:

It starts by dividing the Public Key by its least prime factor.

The example shown below does a Prime Factorization of the Public Key into two prime numbers which equal the Secret Keys.

    21     -- Public Key
     /\
   3  7    -- Secret Keys are the unique Prime Factorization of the Public Key.

The above Public Key is a small number to make it easier to explain the relationship between the Public Key and the Secret Keys. In reality the Public Key would be a very large number that would take a very long time to determine the Prime Factorization even using a computer. Transactions would be completed before the Prime Factorizations would be computed.

2. HASKELL PROGRAM

The Haskell program is as follows:

-- C:\Users\Tinnel\Haskell2024\cryptography.hs

import Data.List
import System.IO

main :: IO ()  -- Has type I/O action.
main = do {  putStrLn ""  -- putStrLn Has type I/O action.
           ; putStrLn "=========================================================="
           ; putStrLn ""
           ; putStrLn "Pretend you are the Bank:"
           ; putStrLn ""
           ; putStrLn "Type a prime number for Secret Key p1 then press Enter."
           ; p1s <- getLine -- getLine is a function, getLine :: IO String
           ; putStrLn ""
           ; putStrLn "Type a prime number for Secret Key p2 then press Enter."
           ; p2s <- getLine
           ; putStrLn ""
           ; putStrLn "=========================================================="
           ; putStrLn ""
           ; putStrLn ("The Secret Keys  p1 and p2 are " ++ p1s ++ " " ++ p2s ++ ".")
           ; putStrLn ""
           ; putStrLn "=========================================================="
           ; putStrLn ""
           ; let p1 = (read p1s)::Integer
           ; let p2 = (read p2s)::Integer
           ; let c = p1 * p2
           ; let cS = show c
           ; putStrLn ("The Public Key is (p1 * p2) which equals " ++ cS ++ ".")
           ; putStrLn ""
           ; putStrLn "=========================================================="
           ; putStrLn ""
           ; putStrLn "The Bank knows the Customer Secret Keys. Therefore,"
           ; putStrLn "the Bank decrypts the Customer Public Key with the Secret Keys."
           ; putStrLn ""
           ; putStrLn "For example, the Bank could compare the product of the Secret Keys with the credit card"
           ; putStrLn "transaction Public Key and if they equal the decryption is successful. Then the Bank can"
           ; putStrLn "process the credit card transaction to the correct Customer credit card account."
           ; putStrLn ""
           ; putStrLn "=========================================================="
           ; putStrLn ""
          }
--  

3. GHCi RUN

*Main> :l cryptography
[1 of 1] Compiling Main             ( cryptography.hs, interpreted )
Ok, modules loaded: Main.
*Main> main

=========================================================================

Pretend you are the Bank:

Type a prime number for Secret Key p1 then press Enter.
3

Type a prime number for Secret Key p2 then press Enter.
7

=========================================================================

The Secret Keys p1 and p2 are 3  7.

=========================================================================

The Public Key is  (p1 * p2) which equals 21.

=========================================================================

The Bank knows the Customer Secret Keys. Therefore,
the Bank decrypts the Customer Public Key with the Secret Keys.

For example, the Bank could compare the product of the Secret Keys with the credit card
transaction Public Key and if they equal the decryption is successful. Then the Bank can
process the credit card transaction to the correct Customer credit card account.

=========================================================================

*Main>

4. CONCLUSION

Using Secret Keys and a Public Key a Bank and a Customer can ensure secure credit card transactions.

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