Write
insensitive
, such thatquickSort' insensitive dictionary
gives["a", "for", "have", "I", "Linux", "thing"]
.
insensitive x y = compare (map toLower x) (map toLower y)
Exercises
(Challenging) The following exercise combines what you have learned about higher order functions, recursion and I/O. We are going to recreate what is known in imperative languages as a for loop. Implement a functionfor :: a -> (a -> Bool) -> (a -> a) -> (a -> IO ()) -> IO () for i p f job = -- ???An example of how this function would be used might be
for 1 (<10) (+1) printwhich prints the numbers 1 to 9 on the screen.
The desired behaviour offor
is: starting from an initial valuei
,for
executesjob i
. It then usesf
to modify this value and checks to see if the modified valuef i
satisfies some conditionp
. If it doesn't, it stops; otherwise, the for loop continues, using the modifiedf i
in place ofi
.
- Implement the for loop in Haskell.
for :: a -> (a -> Bool) -> (a -> a) -> (a -> IO ()) -> IO ()
for i p f job
| p i = do
job i
for (f i) p f job
| otherwise = return ()
- The paragraph just above gives an imperative description of the for loop. Describe your implementation in more functional terms.
The for loop is a recursive function that returns the empty action for the base case if the condition being met. For other cases it executes the action, and then calls itself with the next i, which is found using f i.
Some more challenging exercises you could try
- Consider a task like "print the list of numbers from 1 to 10". Given that
map
sounds like the natural thing to do. But would it actually work?
No, because the 'print' function returns an action, and so would need to be sequenced with the 'do' command.
- Implement a function
sequenceIO :: [IO a] -> IO [a]
. Given a list of actions, this function runs each of the actions in order and returns all their results as a list.
sequenceIO :: [IO a] -> IO [a]
sequenceIO [] = do
return []
sequenceIO (x:xs) = do
r <- x
rs <- (sequenceIO xs)
return (r:rs)
I got most of the way there, but I had the last line as:
return r:rs
I had to look up the answer, and found that of course the parentheses were needed.
- Implement a function
mapIO :: (a -> IO b) -> [a] -> IO [b]
which given a function of typea -> IO b
and a list of type[a]
, runs that action on each item in the list, and returns the results.
mapIO :: (a -> IO b) -> [a] -> IO [b]
mapIO _ [] = return []
mapIO f (x:xs) = do
v <- f x
vs <- (mapIO f xs)
return (v:vs)
This exercise was inspired from a blog post by osfameron. No peeking!