Implement the factorial function in the io monad

Assignment Help Programming Languages
Reference no: EM13854652

import Data.Array
import Data.IORef (newIORef, readIORef, writeIORef)

You will need to consult the documentation on the imported modules.

Please note: ghci will evaluate expressions, of course, but if the expression is of type (IO a), its value will be *executed* and the resulting value in type a showed.

QUESTION 1

Use imperative-style programming to implement the factorial function in the IO monad. In other words, create and initialize variables (references) using newIORef, modify their values using a while loop with ,readIORef and writeIORef, then have the IO action return a pair consisting of the input (n) and the final result. The expression named mod3 below gives a small example of this kind of programming.

Reading:
- LYAH Chapter 9 "Input and Output" up to the first occurrence of "Control.Monad".
- Module documentation for the functions imported from Data.IORef (see the top of this file).

-}

while :: IO Bool -> IO () -> IO ()
while test body =
do b <- test
if b
then do {body ; while test body} -- same-line syntax for do
else return ()

-- remainder when integer-dividing n by 3
mod3 :: Integer -> IO Integer
mod3 n = do r <- newIORef n
while
(do {v <- readIORef r; return (v >= 3)})
(do {v <- readIORef r; writeIORef r (v-3)})
readIORef r

-- ghci> fact 4
-- 24
fact :: Integer -> IO (Integer, Integer)
fact n =
do
undefined

{- CODE FOR QUESTIONS 2 AND 3

Below we give a roll-your-own alternative to Data.IORef. We model memory as an array and memory locations (references) as indices into the array. Using this model it is straightforward to implement creation, reading and writing of references.

However, as with the IO monad, we use a layer of abstraction to hide all the details of memory management. Instead of (IO a), we will have (MM a) -- "MM" for "memory modifiers".

The implementation of actions in (IO a) is completely hidden from us in Haskell. The actions in (MM a) will all be constructed from scratch using the usual kinds of Haskell data. The basic decision in designing MM is how represent actions.

Since we're focusing on references, it's natural to consider an action as something, that in addition to producing a value, modifies memory.

Modifying something in a functional setting is done by applying a function which produces the new "modified" copy. Thus an action can be thought of as a function that takes a memory (array), and from it produces both a value and a new memory (an array with possibly some values updated).

More formally, actions in (MM a) are elements of the type

Mem -> (Mem,a)

so we define

data MM a = MM (Mem -> (Mem, a))

We want to use the same "do" syntax to hide memory management details that IO does. Fortunately, it turns out that MM is a monad.

The definition of (>>=) for MM is not immediately transparent, but it need not be to do Question 2. For question 2, MM can be thought of as replacement for IO and programs using "do" can be constructed analogously. Question 3 requires understanding details of the construction of MM and its operations.

-}

-- for convenience
type Z = Integer

-- raise an error if an attempt to index the array is out of bounds
checkBounds :: String -> Z -> Array Z a -> ()
checkBounds msg i a =
let (lower, upper) = bounds a
in if i >= lower && i < upper
then ()
else error msg

-- Memory is modeled by (Mem n i a) where:
-- - n is the size of the memory (number of locations)
-- - a is an array, with indexes 0<=i<n, representing the
-- values stored in memory and
-- - i is the next position to allocate at
data Mem = Mem Z Z (Array Z Z)
deriving Show

-- A reference is an index into the memory array.
type Ref = Z

-- Memory-modifying computations with result type a.
data MM a = MM (Mem -> (Mem, a))

-- ignore, not needed for either question!
instance Functor MM where
fmap f (MM g) = MM (\m -> let (m',v) = g m in (m', f v))

-- ignore, not needed for either question!
instance Applicative MM where
pure x = MM (\m -> (m,x))
MM f <*> MM g =
MM (\m-> let (m', f') = f m
(m'', x) = g m'
in (m'', f' x))

instance Monad MM where

-- action that produces x without modifying memory
return x = MM (\m -> (m,x))

-- like composing f and g, except memory modifications are chained
(MM a) >>= f =
MM (\m-> let (m', v) = a m
MM b = f v
in b m')

-- create an initial memory of size n
initMem :: Z -> Mem
initMem n = Mem n 0 (array (0,n) [])

-- return a new reference, initialized to v
newRef :: Z -> MM Ref
newRef v =
MM f where
f (Mem n i a) = (m', i )
where m' = Mem n (i+1) a'
a' = a // [(i,v)]

writeRef :: Ref -> Z -> MM ()
writeRef j v =
MM f where f (Mem n i a) = (Mem n i a', ())
where a' = a // [(j,v)]

readRef :: Ref -> MM Z
readRef j =
MM f where f m@(Mem _ _ a) = (m, a!j)

run :: Z -> MM a -> a
run n (MM mm) =
snd $ mm (initMem n)

-- run the action and return a list of memory contents
runDump :: Z -> MM a -> [Z]
runDump n (MM mm) =
elems a where
Mem _ _ a = fst $ mm (initMem n)

-- The test needs to be in MM Bool instead of just Bool because it
-- will generally need to refer to values stored in memory.
while' :: MM Bool -> MM () -> MM ()
while' test body =
do b <- test
if b
then do {body ; while' test body}
else return ()

{- QUESTION 2

Repeat Question 1, but using MM and its reference operations in place of IO, and while' in place of while. You can execute elements of (MM a) using the run function above (which also takes an argument for the size of memory to use).

ghci> run 10 (fact' 4)
24

-}

fact' :: Integer -> MM (Integer, Integer)
fact' n =
do undefined

{- QUESTION 3 -- EXTRA CREDIT

Implement versions of newRef, writeRef and readRef that, instead of returning a single reference, allocate a pair of consecutive storage locations and return the first address (index). Effectively, the operations deal with 2-cell objects. The advantage of this is that linked structures, like linked lists, can be implemented.

Below is given the types for the new operations, and a program appendTest that creates two linked lists then appends them by changing the pointer at the end of the first list. The example uses some auxiliary functions. You just need to implement the three reference operations.

-}

newRef2 :: Z -> Z -> MM Ref
newRef2 u v =
undefined

writeRef2 :: Ref -> Z -> Z -> MM ()
writeRef2 j u v =
undefined

readRef2 :: Ref -> MM (Z,Z)
readRef2 j =
undefined

mkList :: [Z] -> MM Ref
-- Use -1 for "nil", i.e. null pointer
mkList [] = return (-1)
mkList (x:xs) =
do tail <- mkList xs
head <- newRef2 x tail
return head

append :: Ref -> Ref -> MM (Ref)
-- x and y must be pointers to lists
append (-1) y = return y
append x y =
do append' x
return x
where append' x =
do (v,i) <- readRef2 x
if i == -1
then writeRef2 x v y
else append' i

collectList :: Ref -> MM [Z]
collectList (-1) = return []
collectList i =
do (x,j) <- readRef2 i
xs <- collectList j
return (x:xs)

-- ghci> run 37 appendTest
-- [1,2,3,4,5,6]
appendTest :: MM [Z]
appendTest =
do l <- mkList [1,2,3]
newRef 17 >> newRef 17 >> newRef 17 -- some irrelevant creations
l' <- mkList [4,5,6]
newRef 17 >> newRef 17 >> newRef 17 -- ditto
x <- append l l'
result <- collectList x
return result

Reference no: EM13854652

Questions Cloud

Advantages and disadvantages of organizations structure : What are the advantages and disadvantages of the organization's structure? What specific problems is your health care organization facing or likely to face? What is your role in solving these issues?
The hidden costs of absenteeism and sick leave : Never Say Never Industries, a 2300-employee firm, has a serious and growing absenteeism problem.  Last year the total  employee-hours lost to absenteeism came to 134,607.
Comments by twiggy forrest regarding iron ore production : Consider the iron ore production industry, and assume that there are just two producers, FM and BHP. Initially assume that both firms are identical in terms of their production costs. If the two firms can cooperate, what should they do in order to..
Identify the most complex user-system interaction : Identify the most complex user-system interaction (input/response couplet) within the normal flow (ie the step with the most number of side effects, or most complex internal logic), and produce an operation contract for that input-response couplet..
Implement the factorial function in the io monad : Use imperative-style programming to implement the factorial function in the IO monad. In other words, create and initialize variables (references) using newIORef, modify their values using a while loop with ,readIORef and writeIORef, then have th..
What is effect of stock dividend on corporations stockholder : What is the effect of a stock dividend on a corporation's stockholders' equity accounts? Which would you rather receive as a stockholder - a cash dividend or a stock dividend? Why?
Result in loss of personal information : Question 1. Social media sites result in loss of personal information because
Determine the federal income tax for 2013 : Determine the Federal income tax for 2013 for the Deans on a joint return - Under the divorce decree, John was obligated to pay alimony and child support?
Determine the effect of adrians gross income : What would be the tax consequences of each of the alternatives assuming that Fran currently deducts the mortgage interest on her tax return -  Determine the effect of Adrians gross income for 2014 & 2015.

Reviews

Write a Review

Programming Languages Questions & Answers

  Write a haskell program to calculates a balanced partition

Write a program in Haskell which calculates a balanced partition of N items where each item has a value between 0 and K such that the difference b/w the sum of the values of first partition,

  Create an application to run in the amazon ec2 service

In this project you will create an application to run in the Amazon EC2 service and you will also create a client that can run on local machine and access your application.

  Explain the process to develop a web page locally

Explain the process to develop a Web page locally

  Write functions

These 14 questions covers java class, Array, link list , generic class.

  Programming assignment

If the user wants to read the input from a file, then the output will also go into a different file . If the user wants to read the input interactively, then the output will go to the screen .

  Write a prolog program using swi proglog

Write a Prolog program using swi proglog

  Create a custom application using eclipse

Create a custom Application Using Eclipse Android Development

  Create a application using the mvc architecture

create a application using the MVC architecture. No scripting elements are allowed in JSP pages.

  Develops bespoke solutions for the rubber industry

Develops bespoke solutions for the rubber industry

  Design a program that models the worms behavior

Design a program that models the worm's behavior.

  Writing a class

Build a class for a type called Fraction

  Design a program that assigns seats on an airplane

Write a program that allows an instructor to keep a grade book and also design and implement a program that assigns seats on an airplane.

Free Assignment Quote

Assured A++ Grade

Get guaranteed satisfaction & time on delivery in every assignment order you paid with us! We ensure premium quality solution document along with free turntin report!

All rights reserved! Copyrights ©2019-2020 ExpertsMind IT Educational Pvt Ltd