Tuesday, May 30, 2023

HASKELL MONAD OVERVIEW

HASKELL MONAD OVERVIEW

REVISED: Wednesday, January 24, 2024


1. INTRODUCTION

What is a monad?

A monad is a type constructor M that comes with two operations:

return: This operation takes a value of type a and returns a value of type M a.

bind: This operation 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 be used to represent a wide variety of computational concepts, such as:

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 a number of 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 state.

3. EXAMPLE

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

import Control.Monad

{-
This function returns a Maybe Integer, representing the result of dividing two numbers.
-}

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

{-
This function uses the `Maybe` monad to print the result of dividing two numbers.
-}

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

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: Wednesday, January 24, 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.