Haskell Assignment Sheet 2
Data, types, and typeclasses
Submission Instructions
Similar to the previous assignment—you must submit a single Haskell file with the following template.
You can download the template using the # button next to the file name. You can also copy any code snippet by hovering over it and clicking the ! button which appears on the top right.
Question 1
Write a function which accepts a list of directions and uses that list to update the position of a point in space. Here is an example of how it should work.
Use the following template.
You will find the following functions useful.
Question 2
Recall the following data type from the lectures.
Write a function
which takes a SimpleIO computation and appends an exclamation mark to every string that is Put. To test this, you will need the following:
For example:
Question 3
Traditionally, monads are triples
⟨M, η:1→M, μ:M2 →M⟩
You are already familiar with η—that’s return in Haskell. But μ is unfamiliar. In Haskell it is called join, and has the type Monad m => m (m a) -> m a. It is possible—and sometimes easier—to define a monad in terms of join instead of (>>=).
Provide a monad instance for the type Arrow r by defining return and join, where join is called arrowJoin, by replacing each
undefined with working code. +
Question 4 (Hard)
Prove that the monad instance you defined in question 3 satisfies the following monad law: +
join . return = id
In practice, this means that, for an arbitrary x :: Arrow r a, you should show the following:
arrowJoin (return x) = x
Write this proof as a comment in your Haskell file.
Assignment02.hs #
module Assignment02 where ! ———————————————————–
— QUESTION 1
———————————————————–
— QUESTION 2
———————————————————–
— QUESTION 3
———————————————————–
— QUESTION 4
Write your answer as a comment here.
Your file name and module name must match the template—any other file or module name will be rejected.
You may not use any imports to solve this lab. If your file contains an import statement, you will get zero marks.
ghci> receiveAndProc
L L L L L U U U D R U # user input
— Represents a direction: left, right, up, down.
data Direction = L | R | U | D
deriving (Show, Read)
— Represents a position on a grid.
type Position = (Int, Int)
— This is where the main work should happen.
— Examples:
— process [L,L,L,U,U] (0,0) == (-3,2)
— process [L,R,U,U,D,R] (1,-1) == (2,0)
process :: [Direction] -> Position -> Position
process = undefined
— This should read a space-separated list of directions
— and determine the new position of the point (0,0).
receiveAndProc :: IO ()
receiveAndProc = do
— Simple parsing for ‘readable’ types. If Haskell can’t
— infer what the return type is from context, you will
— need to provide it like this:
— read @Int :: String -> Int
— read @Direction :: String -> Direction
— The @-symbol is, in this context, a ‘type application’
— operator — it specialises the type signature to a type
— that implements the Read typeclass.
read :: Read a => String -> a
— Splits a string by whitespace.
— Example:
— words “1 2\n3” == [“1”, “2”, “3”]
words :: String -> [String]
— Applies a function to each of the elements of a list.
— Example:
— map (+1) [1,2,3] == [2,3,4]
map :: (a -> b) -> [a] -> [b]
data SimpleIO a
= Put String (SimpleIO a)
| Get (String -> SimpleIO a)
| Return a
exclaim :: SimpleIO a -> SimpleIO a
exclaim = undefined
io :: SimpleIO a -> IO a
io computation =
case computation of
Put s rest -> do
putStrLn s
Get k -> do
s <- getLine
Return a ->
example :: SimpleIO ()
Put “Hello” $
Get $ \name ->
Put (“My name is ” ++ name) $
ghci> io example
Conor # user input
My name is Conor
ghci> io (exclaim example)
Conor # user input
My name is Conor!
newtype Arrow r a = Arrow { apply :: r -> a }
deriving (Functor, Applicative)
instance Monad (Arrow r) where
return a = undefined
m >>= f = arrowJoin (fmap f m)
arrowJoin :: Arrow r (Arrow r a) -> Arrow r a
arrowJoin arrow = undefined
© Conor Reynolds 2022–2023 ! ” # $ ✉
Programming Help, Add QQ: 749389476